@sema-agent/server 7.135.0 → 7.137.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 (342) hide show
  1. package/MIGRATION.md +237 -2
  2. package/USAGE.md +146 -41
  3. package/deploy/sema-up/README.md +15 -1
  4. package/deploy/sema-up/chart/templates/NOTES.txt +1 -1
  5. package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +7 -1
  6. package/deploy/sema-up/chart/values.yaml +1 -1
  7. package/deploy/sema-up/stack/sema-stack-cluster.yaml +7 -1
  8. package/dist/approval-card.d.ts +60 -4
  9. package/dist/approval-card.js +18 -1
  10. package/dist/approval-content-kind.d.ts +7 -0
  11. package/dist/approval-content-kind.js +8 -1
  12. package/dist/approval-gate-currency.d.ts +48 -6
  13. package/dist/approval-gate-currency.js +16 -9
  14. package/dist/approval-hmac.d.ts +13 -1
  15. package/dist/approval-hmac.js +1 -1
  16. package/dist/approval.js +3 -3
  17. package/dist/auth-bridge.d.ts +34 -5
  18. package/dist/auth-bridge.js +22 -5
  19. package/dist/boot/budget-tracing.d.ts +1 -2
  20. package/dist/boot/budget-tracing.js +2 -2
  21. package/dist/boot/execution-env.d.ts +24 -1
  22. package/dist/boot/execution-env.js +69 -6
  23. package/dist/boot/org-memory.js +1 -1
  24. package/dist/boot/reapers.d.ts +3 -0
  25. package/dist/boot/reapers.js +15 -1
  26. package/dist/boot/resolve-spec.d.ts +4 -0
  27. package/dist/boot/resolve-spec.js +24 -22
  28. package/dist/boot/runner-deps.js +4 -2
  29. package/dist/boot/stage-03-store-backend.d.ts +1 -1
  30. package/dist/boot/stage-04-stores.d.ts +2 -2
  31. package/dist/boot/stage-05-execution-env.d.ts +4 -2
  32. package/dist/boot/stage-05-execution-env.js +11 -2
  33. package/dist/boot/stage-06-runners.d.ts +4 -2
  34. package/dist/boot/stage-06-runners.js +5 -1
  35. package/dist/boot/stage-07-capability-layer.d.ts +5 -2
  36. package/dist/boot/stage-07-capability-layer.js +1 -1
  37. package/dist/boot/stage-08-reapers.d.ts +5 -2
  38. package/dist/boot/stage-08-reapers.js +2 -1
  39. package/dist/boot/stage-09-leader.d.ts +5 -2
  40. package/dist/boot/stage-10-http-server.d.ts +5 -2
  41. package/dist/boot/stage-10-http-server.js +3 -2
  42. package/dist/boot/stores.d.ts +1 -1
  43. package/dist/boot/stores.js +2 -3
  44. package/dist/boot/web-admin.js +10 -17
  45. package/dist/brain.js +12 -3
  46. package/dist/broker/broker.d.ts +89 -0
  47. package/dist/broker/broker.js +287 -0
  48. package/dist/broker/constants.d.ts +39 -0
  49. package/dist/broker/constants.js +15 -0
  50. package/dist/broker/http1.d.ts +111 -0
  51. package/dist/broker/http1.js +256 -0
  52. package/dist/broker/lease-book.d.ts +87 -0
  53. package/dist/broker/lease-book.js +142 -0
  54. package/dist/broker/lease-file.d.ts +60 -0
  55. package/dist/broker/lease-file.js +127 -0
  56. package/dist/broker/main.d.ts +2 -0
  57. package/dist/broker/main.js +20 -0
  58. package/dist/budget.d.ts +3 -3
  59. package/dist/budget.js +4 -0
  60. package/dist/capabilities/composite-members.d.ts +2 -1
  61. package/dist/capabilities/composite-members.js +2 -1
  62. package/dist/capabilities/engine-capabilities.js +1 -0
  63. package/dist/capabilities/mcp-probe.d.ts +5 -4
  64. package/dist/capabilities/scenarios.d.ts +23 -8
  65. package/dist/capabilities/scenarios.js +13 -8
  66. package/dist/capabilities/skills.d.ts +28 -5
  67. package/dist/capabilities/skills.js +8 -0
  68. package/dist/capability-facts.d.ts +3 -7
  69. package/dist/capability-facts.js +3 -5
  70. package/dist/center-credential-renewer.js +5 -1
  71. package/dist/center-credential.d.ts +18 -4
  72. package/dist/center-credential.js +18 -3
  73. package/dist/checkpoint-ctx-seal-m28.d.ts +3 -10
  74. package/dist/checkpoint-ctx-seal-m28.js +1 -1
  75. package/dist/checkpoint-identity.d.ts +3 -3
  76. package/dist/config-catalog.js +21 -16
  77. package/dist/config-d-migration.js +1 -1
  78. package/dist/config-invariants.d.ts +1 -1
  79. package/dist/config-invariants.js +8 -0
  80. package/dist/config-lkg.d.ts +0 -38
  81. package/dist/config-lkg.js +1 -83
  82. package/dist/config-types.d.ts +21 -4
  83. package/dist/config.d.ts +1 -1
  84. package/dist/config.js +60 -16
  85. package/dist/deployment-governance.d.ts +2 -2
  86. package/dist/deployment-governance.js +7 -9
  87. package/dist/deployment-shape.d.ts +1 -1
  88. package/dist/device-ws-protocol.d.ts +1 -0
  89. package/dist/device-ws-protocol.js +2 -1
  90. package/dist/elicitation.d.ts +8 -7
  91. package/dist/elicitation.js +9 -8
  92. package/dist/file-history-disclosure.d.ts +8 -4
  93. package/dist/file-history-disclosure.js +24 -6
  94. package/dist/fleet-client.d.ts +32 -1
  95. package/dist/fleet-client.js +24 -4
  96. package/dist/fleet-lease.d.ts +7 -3
  97. package/dist/fleet-lease.js +31 -23
  98. package/dist/hooks/classic-stations.d.ts +11 -54
  99. package/dist/hooks/hook-llm.js +14 -8
  100. package/dist/hooks/hook-runner.d.ts +4 -4
  101. package/dist/hooks/hook-runner.js +2 -2
  102. package/dist/http/admission.js +10 -7
  103. package/dist/http/approval-sweeps.js +4 -3
  104. package/dist/http/caller-trust.d.ts +2 -1
  105. package/dist/http/caller-trust.js +1 -3
  106. package/dist/http/checkpoint-ctx.d.ts +76 -16
  107. package/dist/http/checkpoint-ctx.js +45 -1
  108. package/dist/http/dispatch.js +24 -19
  109. package/dist/http/durable-run-leg.d.ts +5 -1
  110. package/dist/http/durable-run-leg.js +1 -1
  111. package/dist/http/health-self-report.d.ts +2 -2
  112. package/dist/http/mcp-remote-text.d.ts +5 -0
  113. package/dist/http/mcp-remote-text.js +7 -0
  114. package/dist/http/principal-gate.d.ts +15 -10
  115. package/dist/http/principal-gate.js +48 -9
  116. package/dist/http/resume-ctx-read.d.ts +2 -16
  117. package/dist/http/resume-ctx-read.js +2 -3
  118. package/dist/http/resume-legs.d.ts +2 -20
  119. package/dist/http/resume-legs.js +52 -38
  120. package/dist/http/route-ctx.d.ts +8 -2
  121. package/dist/http/routes/approvals-assistant.d.ts +0 -2
  122. package/dist/http/routes/approvals-assistant.js +65 -16
  123. package/dist/http/routes/capabilities.js +11 -1
  124. package/dist/http/routes/mcp-reconnect.d.ts +1 -1
  125. package/dist/http/routes/mcp-reconnect.js +5 -7
  126. package/dist/http/routes/runs.js +4 -3
  127. package/dist/http/routes/session-sync.js +70 -12
  128. package/dist/http/routes/sessions.js +20 -15
  129. package/dist/http/routes/tasks.js +8 -6
  130. package/dist/http/server.d.ts +4 -0
  131. package/dist/http/stored-body-replay.d.ts +3 -3
  132. package/dist/http/stored-body-replay.js +6 -1
  133. package/dist/http/submit-ctx.js +1 -1
  134. package/dist/http/wire-types.d.ts +57 -30
  135. package/dist/identity-source.d.ts +65 -0
  136. package/dist/identity-source.js +45 -0
  137. package/dist/index.d.ts +1 -0
  138. package/dist/index.js +1 -0
  139. package/dist/memory-store-refusal.d.ts +3 -3
  140. package/dist/model-entry-refusal.d.ts +2 -0
  141. package/dist/model-entry-refusal.js +11 -0
  142. package/dist/model-route-gap.d.ts +49 -4
  143. package/dist/model-route-gap.js +34 -1
  144. package/dist/model-select.d.ts +6 -17
  145. package/dist/model-select.js +0 -3
  146. package/dist/namespaced-rule-name.d.ts +1 -1
  147. package/dist/object-store-buckets.d.ts +13 -0
  148. package/dist/object-store-buckets.js +3 -0
  149. package/dist/observability/fail-open.d.ts +19 -7
  150. package/dist/observability/fail-open.js +19 -7
  151. package/dist/observability/metrics.js +2 -2
  152. package/dist/observability/principal-context.d.ts +4 -1
  153. package/dist/observability/principal-context.js +6 -1
  154. package/dist/observability/run-terminal.js +1 -0
  155. package/dist/operator-ask.d.ts +2 -2
  156. package/dist/org-delivery-gate.js +1 -1
  157. package/dist/org-memory-admission.d.ts +2 -2
  158. package/dist/org-memory-admission.js +39 -2
  159. package/dist/parked-decide.d.ts +4 -3
  160. package/dist/parked-decide.js +29 -9
  161. package/dist/peer-directory.d.ts +2 -1
  162. package/dist/peer-directory.js +7 -5
  163. package/dist/permission-rule-list.d.ts +2 -2
  164. package/dist/plugins/approval-ask-store-sql.d.ts +8 -0
  165. package/dist/plugins/approval-ask-store-sql.js +3 -0
  166. package/dist/plugins/blob-backend.js +2 -1
  167. package/dist/plugins/checkpoint-index-columns.d.ts +50 -1
  168. package/dist/plugins/checkpoint-index-columns.js +28 -0
  169. package/dist/plugins/checkpoint-store-sql.d.ts +46 -12
  170. package/dist/plugins/checkpoint-store-sql.js +64 -35
  171. package/dist/plugins/file-history-store-sql.d.ts +6 -0
  172. package/dist/plugins/file-history-store-sql.js +37 -37
  173. package/dist/plugins/file-run-store.js +8 -2
  174. package/dist/plugins/k8s-exec-protocol.d.ts +69 -13
  175. package/dist/plugins/k8s-exec-protocol.js +116 -28
  176. package/dist/plugins/k8s-pod-delete-failure.d.ts +25 -0
  177. package/dist/plugins/k8s-pod-delete-failure.js +17 -0
  178. package/dist/plugins/k8s-pod-reaper.d.ts +112 -0
  179. package/dist/plugins/k8s-pod-reaper.js +122 -0
  180. package/dist/plugins/local-checkpoint-store.d.ts +3 -6
  181. package/dist/plugins/local-checkpoint-store.js +7 -6
  182. package/dist/plugins/memory-run-store.js +2 -0
  183. package/dist/plugins/one-time-migrations.d.ts +49 -37
  184. package/dist/plugins/one-time-migrations.js +87 -128
  185. package/dist/plugins/permission-rule-store-file.js +2 -2
  186. package/dist/plugins/permission-rule-store-sql.d.ts +17 -17
  187. package/dist/plugins/permission-rule-store-sql.js +16 -17
  188. package/dist/plugins/pg-pool.js +4 -0
  189. package/dist/plugins/pg-session-storage.js +2 -2
  190. package/dist/plugins/remote-env-adb.d.ts +3 -0
  191. package/dist/plugins/remote-env-adb.js +1 -0
  192. package/dist/plugins/remote-env-device.d.ts +3 -0
  193. package/dist/plugins/remote-env-device.js +4 -0
  194. package/dist/plugins/remote-env-e2b.d.ts +3 -0
  195. package/dist/plugins/remote-env-e2b.js +1 -0
  196. package/dist/plugins/remote-env-file-error.d.ts +8 -1
  197. package/dist/plugins/remote-env-file-error.js +7 -1
  198. package/dist/plugins/remote-env-host.d.ts +7 -1
  199. package/dist/plugins/remote-env-host.js +7 -1
  200. package/dist/plugins/remote-env-k8s.d.ts +154 -14
  201. package/dist/plugins/remote-env-k8s.js +300 -21
  202. package/dist/plugins/remote-env-local-docker.d.ts +3 -0
  203. package/dist/plugins/remote-env-local-docker.js +1 -0
  204. package/dist/plugins/remote-env-ssh.d.ts +3 -0
  205. package/dist/plugins/remote-env-ssh.js +1 -0
  206. package/dist/plugins/run-store-sql.js +10 -4
  207. package/dist/plugins/s3-answer.d.ts +15 -0
  208. package/dist/plugins/s3-answer.js +5 -0
  209. package/dist/plugins/session-ownership.d.ts +17 -3
  210. package/dist/plugins/session-ownership.js +19 -5
  211. package/dist/plugins/snapshot-bucket-presence.d.ts +39 -4
  212. package/dist/plugins/snapshot-bucket-presence.js +35 -7
  213. package/dist/plugins/sql-errors.d.ts +60 -0
  214. package/dist/plugins/sql-errors.js +64 -1
  215. package/dist/plugins/store-contracts.d.ts +10 -1
  216. package/dist/plugins/store-fault.d.ts +4 -0
  217. package/dist/plugins/store-fault.js +10 -0
  218. package/dist/plugins/tidb-pool.js +8 -1
  219. package/dist/plugins/tidb-session-store.js +2 -2
  220. package/dist/plugins/web-search.d.ts +1 -1
  221. package/dist/plugins/web-search.js +2 -2
  222. package/dist/request-declaration-refusal.d.ts +94 -0
  223. package/dist/request-declaration-refusal.js +78 -0
  224. package/dist/request-image-urls.d.ts +6 -0
  225. package/dist/request-image-urls.js +27 -0
  226. package/dist/request-key-closure.d.ts +5 -0
  227. package/dist/request-key-closure.js +5 -2
  228. package/dist/request-value-closure.d.ts +31 -2
  229. package/dist/request-value-closure.js +7 -1
  230. package/dist/rule-entry-list.d.ts +3 -2
  231. package/dist/rule-entry-list.js +2 -2
  232. package/dist/rules-consent.js +7 -4
  233. package/dist/run-local.d.ts +2 -2
  234. package/dist/runs.js +2 -1
  235. package/dist/runtime-caps-resolver.js +1 -1
  236. package/dist/runtime-governance.d.ts +5 -5
  237. package/dist/sandbox-git-lease.d.ts +49 -0
  238. package/dist/sandbox-git-lease.js +60 -0
  239. package/dist/sandbox-git-plane.d.ts +84 -0
  240. package/dist/sandbox-git-plane.js +105 -0
  241. package/dist/sandbox-pkg-source.d.ts +28 -1
  242. package/dist/sandbox-pkg-source.js +1 -2
  243. package/dist/sealed-key.d.ts +19 -0
  244. package/dist/sealed-key.js +47 -4
  245. package/dist/security.d.ts +16 -4
  246. package/dist/security.js +8 -3
  247. package/dist/server-secret-env.d.ts +6 -0
  248. package/dist/server-secret-env.js +14 -0
  249. package/dist/session-error-wire.d.ts +14 -6
  250. package/dist/session-error-wire.js +2 -1
  251. package/dist/session-incarnation.d.ts +16 -5
  252. package/dist/session-incarnation.js +7 -4
  253. package/dist/session-policy-wire.d.ts +1 -1
  254. package/dist/session-policy-wire.js +2 -2
  255. package/dist/session-row.d.ts +3 -17
  256. package/dist/session-row.js +4 -0
  257. package/dist/session-sync.d.ts +15 -3
  258. package/dist/session-sync.js +5 -2
  259. package/dist/spec-fields.d.ts +43 -13
  260. package/dist/spec-fields.js +33 -12
  261. package/dist/stored-request-prompt-profile-m30.d.ts +49 -0
  262. package/dist/stored-request-prompt-profile-m30.js +25 -0
  263. package/dist/task-a2a.d.ts +52 -81
  264. package/dist/task-a2a.js +219 -89
  265. package/dist/task-mcp.d.ts +7 -15
  266. package/dist/task-mcp.js +16 -51
  267. package/dist/task-settings.d.ts +2 -2
  268. package/dist/tool-approval.d.ts +35 -12
  269. package/dist/tool-approval.js +59 -39
  270. package/dist/tool-rule-names.d.ts +5 -0
  271. package/dist/trace/core-keyset-guard.d.ts +5 -5
  272. package/dist/trace/engine-notice-wire.d.ts +1 -1
  273. package/dist/trace/engine-notice-wire.js +2 -0
  274. package/dist/trace/exit-seat.js +37 -13
  275. package/dist/trace/ledger-sink.d.ts +4 -5
  276. package/dist/trace/ledger-sink.js +3 -7
  277. package/dist/trace/project.d.ts +37 -3
  278. package/dist/trace/project.js +20 -6
  279. package/dist/trace/redact.d.ts +40 -12
  280. package/dist/trace/redact.js +332 -128
  281. package/dist/trace/self-minted-wire.d.ts +641 -0
  282. package/dist/trace/self-minted-wire.js +201 -0
  283. package/dist/trace/wire-projection-faces.d.ts +5 -3
  284. package/dist/trace/wire-projection-faces.js +7 -3
  285. package/dist/url-credential-refusal.d.ts +52 -0
  286. package/dist/url-credential-refusal.js +14 -0
  287. package/dist/url-refusal.d.ts +13 -4
  288. package/dist/url-refusal.js +8 -2
  289. package/dist/web-admin-client/apply-effective.js +0 -1
  290. package/dist/web-admin-client/center-request.d.ts +20 -2
  291. package/dist/web-admin-client/center-request.js +40 -5
  292. package/dist/web-admin-client/http-client.js +6 -6
  293. package/dist/web-admin-client/types.d.ts +5 -5
  294. package/dist/workspace-space.d.ts +27 -0
  295. package/dist/workspace-space.js +26 -0
  296. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +11 -5
  297. package/package.json +4 -3
  298. package/scripts/drain-check-local.mjs +2 -1
  299. package/scripts/drain-check.mysql.sql +3 -1
  300. package/scripts/drain-check.pg.sql +3 -1
  301. package/skills/schedule.md +1 -1
  302. package/wire-changes/server@7.104.0.json +134 -0
  303. package/wire-changes/server@7.105.0.json +53 -0
  304. package/wire-changes/server@7.106.0.json +475 -0
  305. package/wire-changes/server@7.107.0.json +64 -0
  306. package/wire-changes/server@7.108.0.json +153 -0
  307. package/wire-changes/server@7.109.0.json +46 -0
  308. package/wire-changes/server@7.110.0.json +90 -0
  309. package/wire-changes/server@7.111.0.json +86 -0
  310. package/wire-changes/server@7.112.0.json +60 -0
  311. package/wire-changes/server@7.113.0.json +26 -0
  312. package/wire-changes/server@7.114.0.json +26 -0
  313. package/wire-changes/server@7.115.0.json +97 -0
  314. package/wire-changes/server@7.116.0.json +218 -0
  315. package/wire-changes/server@7.116.1.json +26 -0
  316. package/wire-changes/server@7.117.0.json +65 -0
  317. package/wire-changes/server@7.118.0.json +129 -0
  318. package/wire-changes/server@7.119.0.json +65 -0
  319. package/wire-changes/server@7.120.0.json +89 -0
  320. package/wire-changes/server@7.121.0.json +219 -0
  321. package/wire-changes/server@7.122.0.json +54 -0
  322. package/wire-changes/server@7.123.0.json +26 -0
  323. package/wire-changes/server@7.124.0.json +336 -0
  324. package/wire-changes/server@7.124.1.json +26 -0
  325. package/wire-changes/server@7.125.0.json +111 -0
  326. package/wire-changes/server@7.126.0.json +285 -0
  327. package/wire-changes/server@7.127.0.json +77 -0
  328. package/wire-changes/server@7.127.1.json +26 -0
  329. package/wire-changes/server@7.127.2.json +53 -0
  330. package/wire-changes/server@7.128.0.json +26 -0
  331. package/wire-changes/server@7.129.0.json +106 -0
  332. package/wire-changes/server@7.129.1.json +26 -0
  333. package/wire-changes/server@7.130.0.json +26 -0
  334. package/wire-changes/server@7.131.0.json +118 -0
  335. package/wire-changes/server@7.132.0.json +226 -0
  336. package/wire-changes/server@7.133.0.json +1155 -0
  337. package/wire-changes/server@7.134.0.json +107 -0
  338. package/wire-changes/server@7.135.0.json +174 -0
  339. package/wire-changes/server@7.136.0.json +448 -0
  340. package/wire-changes/server@7.137.0.json +825 -0
  341. package/dist/url-credential.d.ts +0 -52
  342. package/dist/url-credential.js +0 -49
@@ -1,5 +1,5 @@
1
1
  import { QuotaLease, leaseExhausted, shouldRenewLease } from "@sema-agent/settings-schema/fleet";
2
- import { CenterCredentialUnavailableError } from "./center-credential.js";
2
+ import { CenterCredentialUnavailableError, createIdentityBins, pinAccountingIdentity } from "./center-credential.js";
3
3
  import { centerFetch, centerLaneConfigured } from "./web-admin-client/center-request.js";
4
4
  export const NOT_LEASE_TTL_MS = 10 * 60 * 1000;
5
5
  export const EXHAUSTED_RETRY_MS = 30 * 1000;
@@ -23,8 +23,7 @@ const LEASE_HEALTH_BY_OUTCOME = {
23
23
  };
24
24
  export class FleetLeaseManager {
25
25
  opts;
26
- state = new Map();
27
- inflight = new Map();
26
+ binNow;
28
27
  f;
29
28
  now;
30
29
  failStreak = 0;
@@ -35,10 +34,19 @@ export class FleetLeaseManager {
35
34
  this.f = opts.fetchImpl ?? fetch;
36
35
  this.now = opts.now ?? Date.now;
37
36
  this.failMode = opts.failMode;
37
+ this.binNow = createIdentityBins(opts.center.credential, (pinned) => ({
38
+ state: new Map(),
39
+ inflight: new Map(),
40
+ center: { ...opts.center, credential: pinned },
41
+ })).accounting;
42
+ }
43
+ pinExecution() {
44
+ pinAccountingIdentity(this.opts.center.credential);
38
45
  }
39
46
  async admit(principal) {
47
+ const bin = this.binNow();
40
48
  const now = this.now();
41
- const st = this.state.get(principal);
49
+ const st = bin.state.get(principal);
42
50
  if (st?.kind === "not-lease" && now < st.until)
43
51
  return { ok: true };
44
52
  if (st?.kind === "exhausted" && now < st.until) {
@@ -46,15 +54,15 @@ export class FleetLeaseManager {
46
54
  }
47
55
  if (st?.kind === "lease" && !leaseExhausted(st.lease, now)) {
48
56
  if (shouldRenewLease(st.lease, now))
49
- void this.issueOrRenew(principal).catch(() => undefined);
57
+ void this.issueOrRenew(bin, principal).catch(() => undefined);
50
58
  return { ok: true };
51
59
  }
52
- return this.issueOrRenew(principal);
60
+ return this.issueOrRenew(bin, principal);
53
61
  }
54
62
  recordSpend(principal, d) {
55
63
  if (!principal)
56
64
  return;
57
- const st = this.state.get(principal);
65
+ const st = this.binNow().state.get(principal);
58
66
  if (st?.kind !== "lease")
59
67
  return;
60
68
  st.lease.consumed.weightedTokens += d.weightedTokens ?? 0;
@@ -62,7 +70,7 @@ export class FleetLeaseManager {
62
70
  }
63
71
  snapshot(principal, now) {
64
72
  const leaseHealth = LEASE_HEALTH_BY_OUTCOME[this.lastAdmit];
65
- const st = principal === undefined ? undefined : this.state.get(principal);
73
+ const st = principal === undefined ? undefined : this.binNow().state.get(principal);
66
74
  if (st === undefined)
67
75
  return { leaseHealth, caller: { lease: "unobserved" } };
68
76
  switch (st.kind) {
@@ -97,25 +105,25 @@ export class FleetLeaseManager {
97
105
  }
98
106
  }
99
107
  }
100
- set(principal, st) {
101
- if (!this.state.has(principal) && this.state.size >= LEASE_PRINCIPAL_CAP) {
102
- const oldest = this.state.keys().next().value;
103
- this.state.delete(oldest);
108
+ set(bin, principal, st) {
109
+ if (!bin.state.has(principal) && bin.state.size >= LEASE_PRINCIPAL_CAP) {
110
+ const oldest = bin.state.keys().next().value;
111
+ bin.state.delete(oldest);
104
112
  }
105
- this.state.delete(principal);
106
- this.state.set(principal, st);
113
+ bin.state.delete(principal);
114
+ bin.state.set(principal, st);
107
115
  }
108
- issueOrRenew(principal) {
109
- const existing = this.inflight.get(principal);
116
+ issueOrRenew(bin, principal) {
117
+ const existing = bin.inflight.get(principal);
110
118
  if (existing)
111
119
  return existing;
112
- const p = this.issueOrRenewInner(principal).finally(() => this.inflight.delete(principal));
113
- this.inflight.set(principal, p);
120
+ const p = this.issueOrRenewInner(bin, principal).finally(() => bin.inflight.delete(principal));
121
+ bin.inflight.set(principal, p);
114
122
  return p;
115
123
  }
116
- async issueOrRenewInner(principal) {
124
+ async issueOrRenewInner(bin, principal) {
117
125
  try {
118
- const { res } = await centerFetch(this.opts.center, { kind: "fleet-leases" }, {
126
+ const { res } = await centerFetch(bin.center, { kind: "fleet-leases" }, {
119
127
  method: "POST",
120
128
  json: { principal, worker: this.opts.center.worker },
121
129
  timeoutMs: LEASE_FETCH_TIMEOUT_MS,
@@ -124,7 +132,7 @@ export class FleetLeaseManager {
124
132
  if (res.status === 200) {
125
133
  const body = (await res.json());
126
134
  const lease = QuotaLease.parse(body.lease);
127
- this.set(principal, { kind: "lease", lease });
135
+ this.set(bin, principal, { kind: "lease", lease });
128
136
  if (this.failStreak > 0)
129
137
  this.opts.logger?.info?.("fleet_lease_recovered", { after: this.failStreak });
130
138
  this.failStreak = 0;
@@ -145,11 +153,11 @@ export class FleetLeaseManager {
145
153
  ...(body.pool !== undefined ? { pool: body.pool } : {}),
146
154
  };
147
155
  const hasDetail = Object.keys(detail).length > 0;
148
- this.set(principal, { kind: "exhausted", until, ...(hasDetail ? { detail } : {}) });
156
+ this.set(bin, principal, { kind: "exhausted", until, ...(hasDetail ? { detail } : {}) });
149
157
  this.opts.metrics?.inc("fleet_lease_exhausted_total");
150
158
  return { ok: false, reason: "budget_exhausted", retryAfterSec: Math.ceil(EXHAUSTED_RETRY_MS / 1000), ...(hasDetail ? { detail } : {}) };
151
159
  }
152
- this.set(principal, { kind: "not-lease", until: this.now() + NOT_LEASE_TTL_MS });
160
+ this.set(bin, principal, { kind: "not-lease", until: this.now() + NOT_LEASE_TTL_MS });
153
161
  return { ok: true };
154
162
  }
155
163
  if (res.status === 401 || res.status === 403 || res.status === 400) {
@@ -2,8 +2,8 @@
2
2
  * 引擎的 `classic.*` 站 —— 本仓挂 handler 的唯一入口(core 7.52.0 起扩展点 = mods 注册,`Hooks` 记录退役)。
3
3
  *
4
4
  * 三件事只写在这里:
5
- * ① **事件名 → { `e` 型, 答案型 }**:core 逐个导出了每站的 `e` 型与答案型,但没有导出二者的映射(宿主侧配对是今天的唯一读法)。
6
- * 这张对位表是那一配对的唯一一份;core 导出映射型的那一版,本表改读它、删掉手写的十一行。
5
+ * ① **事件名 → { `e` 型, 答案型 }**:读 core 的 `ClassicEventMap`(7.56.0 起包根导出;此前本文件手写十一行配对,随之删)。
6
+ * 每站的角色(链 / 观察)由 {@link CLASSIC_STATION_ROLE} 说,它在编译期对着 core 的答案形核:答案形是 `ObservedAnswer` 的站必须是 `observe`、其余是 `chain`。
7
7
  * ② **handler 怎么挂**:链成员「无意见 ⇒ `next(e)`」(链 handler 返回 `undefined` 是站点违约,refuse 站上即 fail-closed 拒),
8
8
  * 观察者「恒返回 `undefined`」(观察者的判词不采纳、被引擎报告)。两条都在 {@link hangClassic} / {@link observeClassic} 里成形,
9
9
  * 调用方只写「这一站我答什么」或「这一站我看什么」,不再各自记得这两条。
@@ -13,55 +13,9 @@
13
13
  * 站的集合 = 引擎事件表里有站的 `classic.*` 名(一条钉从 `MOD_EVENT_TABLE` 派生对拍,不手抄第二份)。
14
14
  * 观察站(`StopFailure` / `PostCompact` / `PermissionDenied`)只许观察者:答案形是「无」,core 的迁移配方要求挂 `{ observe: true }`。
15
15
  */
16
- import type { EngineDollar, On, PermissionDeniedPayload, PostCompactEvent, PostToolBatchEvent, PostToolBatchResult, PostToolUseEvent, PostToolUseFailureEvent, PostToolUseFailureResult, PostToolUseResult, PreCompactEvent, PreCompactResult, PreToolUseEvent, PreToolUseResult, StopEvent, StopFailureEvent, StopHookResult, UserPromptSubmitEvent, UserPromptSubmitResult } from "@sema-agent/core";
17
- /** 每一站的 `e` 型与答案型(答案 `void` = 观察站)。 */
18
- export interface ClassicStationTypes {
19
- "classic.PreToolUse": {
20
- e: PreToolUseEvent;
21
- answer: PreToolUseResult;
22
- };
23
- "classic.PostToolUse": {
24
- e: PostToolUseEvent;
25
- answer: PostToolUseResult;
26
- };
27
- "classic.PostToolUseFailure": {
28
- e: PostToolUseFailureEvent;
29
- answer: PostToolUseFailureResult;
30
- };
31
- "classic.PostToolBatch": {
32
- e: PostToolBatchEvent;
33
- answer: PostToolBatchResult;
34
- };
35
- "classic.UserPromptSubmit": {
36
- e: UserPromptSubmitEvent;
37
- answer: UserPromptSubmitResult;
38
- };
39
- "classic.Stop": {
40
- e: StopEvent;
41
- answer: StopHookResult;
42
- };
43
- "classic.SubagentStop": {
44
- e: StopEvent;
45
- answer: StopHookResult;
46
- };
47
- "classic.StopFailure": {
48
- e: StopFailureEvent;
49
- answer: void;
50
- };
51
- "classic.PreCompact": {
52
- e: PreCompactEvent;
53
- answer: PreCompactResult;
54
- };
55
- "classic.PostCompact": {
56
- e: PostCompactEvent;
57
- answer: void;
58
- };
59
- "classic.PermissionDenied": {
60
- e: PermissionDeniedPayload;
61
- answer: void;
62
- };
63
- }
64
- export type ClassicStation = keyof ClassicStationTypes;
16
+ import type { ClassicEventMap, ClassicEventName, EngineDollar, On } from "@sema-agent/core";
17
+ /** 引擎有站的 `classic.*` 名(core 的 `ClassicEventMap` 键集)。 */
18
+ export type ClassicStation = ClassicEventName;
65
19
  /** 每一站能挂什么:`chain` = 链成员(会作答)与观察者都可;`observe` = 只许观察者。 */
66
20
  export declare const CLASSIC_STATION_ROLE: {
67
21
  readonly "classic.PreToolUse": "chain";
@@ -76,16 +30,19 @@ export declare const CLASSIC_STATION_ROLE: {
76
30
  readonly "classic.PostCompact": "observe";
77
31
  readonly "classic.PermissionDenied": "observe";
78
32
  };
33
+ /** 本仓 handler 体对一站作的答:观察站不作答(`void`);链站 = core 的答案形,去掉本仓从不作的 `null` / `false`(PreToolUse 的两个「不表态」词)。 */
34
+ type StationAnswer<K extends ClassicStation> = (typeof CLASSIC_STATION_ROLE)[K] extends "observe" ? void : Exclude<ClassicEventMap[K]["answer"], null | false>;
79
35
  /**
80
36
  * 一站的 handler 体:读 `e`,答这一站的答案;`undefined` = 无意见(链成员由 {@link hangClassic} 交给 `next(e)`)。
81
37
  * `signal` = 引擎交给这只 handler 的 `next.signal`(预算到 ∪ 派发被取消;见头注 ③)。
82
38
  */
83
- export type ClassicAnswer<K extends ClassicStation> = (e: ClassicStationTypes[K]["e"], signal: AbortSignal) => Promise<ClassicStationTypes[K]["answer"] | undefined>;
39
+ export type ClassicAnswer<K extends ClassicStation> = (e: ClassicEventMap[K]["e"], signal: AbortSignal) => Promise<StationAnswer<K> | undefined>;
84
40
  /**
85
41
  * 按站的角色挂一只 handler:链站 ⇒ 链成员 `(await answer(e)) ?? next(e)`;观察站 ⇒ 观察者(体照跑、恒返回 `undefined`)。
86
- * `e` 的型由 {@link ClassicStationTypes} 给(引擎交来的是本站的 `e`;配对见头注 ①)。
42
+ * `e` 的型由 core 的 `ClassicEventMap` 给(引擎交来的是本站的 `e`;见头注 ①)。
87
43
  */
88
44
  export declare function hangClassic<K extends ClassicStation>(on: On<EngineDollar>, station: K, answer: ClassicAnswer<K>): void;
89
45
  /** 挂一只观察者(任何站都可):拿分离副本、不进链、恒返回 `undefined`;`signal` 同 {@link ClassicAnswer}。 */
90
- export declare function observeClassic<K extends ClassicStation>(on: On<EngineDollar>, station: K, watch: (e: ClassicStationTypes[K]["e"], signal: AbortSignal) => void | Promise<void>): void;
46
+ export declare function observeClassic<K extends ClassicStation>(on: On<EngineDollar>, station: K, watch: (e: ClassicEventMap[K]["e"], signal: AbortSignal) => void | Promise<void>): void;
47
+ export {};
91
48
  //# sourceMappingURL=classic-stations.d.ts.map
@@ -2,6 +2,7 @@ import { admitRouteRequest, BrainError, joinRequestUrl, resolveRouteCredential,
2
2
  import { matchCatalogModel, refusedCatalogEntry, servedModelTableLeg } from "../model-select.js";
3
3
  import { echoModelRef, modelUnavailableMessage } from "../model-entry-refusal.js";
4
4
  import { resolveOpenaiRouteEndpoint } from "../model-route-endpoint.js";
5
+ import { anthropicLaneCredentialOf } from "../model-route-gap.js";
5
6
  import { anthropicRouteRoot, brainLaneFor, routeTableOf } from "../model-provider.js";
6
7
  import { egressRedirectRefusal } from "../egress-redirect.js";
7
8
  import { buildDisplaySafeRefusal, redactSecrets } from "../trace/redact.js";
@@ -33,6 +34,16 @@ function gateRefusal(pick, e, declaredRoot) {
33
34
  error: `hook model "${pick.catalogRef}" cannot be routed (${code}) — ` + buildDisplaySafeRefusal(text, [pick.baseUrl, declaredRoot ?? ""]),
34
35
  };
35
36
  }
37
+ function routeCredentialHeader(credential) {
38
+ if (credential === undefined)
39
+ return {};
40
+ switch (credential.kind) {
41
+ case "x-api-key":
42
+ return { "x-api-key": credential.value };
43
+ case "bearer":
44
+ return { authorization: `Bearer ${credential.value}` };
45
+ }
46
+ }
36
47
  export function createHookLlm(deps) {
37
48
  const { config, metrics } = deps;
38
49
  const anthropicRouteBaseUrl = () => anthropicRouteRoot(config.anthropic ?? {});
@@ -122,9 +133,10 @@ export function createHookLlm(deps) {
122
133
  let admitted;
123
134
  let declaredRoot;
124
135
  if (pick.api === "anthropic-messages") {
136
+ const routeCredential = anthropicLaneCredentialOf(config.anthropic ?? {});
125
137
  const routeBase = anthropicRouteBaseUrl();
126
138
  declaredRoot = routeBase;
127
- const routed = judgeRoute(pick, perModelKey, config.anthropic?.authToken ?? config.anthropic?.apiKey, routeBase);
139
+ const routed = judgeRoute(pick, perModelKey, routeCredential?.value, routeBase);
128
140
  if (!routed.ok)
129
141
  return routed;
130
142
  admitted = routed.admission;
@@ -132,13 +144,7 @@ export function createHookLlm(deps) {
132
144
  headers = {
133
145
  "content-type": "application/json",
134
146
  "anthropic-version": config.anthropic?.version ?? "2023-06-01",
135
- ...(routed.credential.source === "per-model"
136
- ? { "x-api-key": routed.credential.apiKey ?? "" }
137
- : config.anthropic?.authToken
138
- ? { authorization: `Bearer ${config.anthropic.authToken}` }
139
- : config.anthropic?.apiKey
140
- ? { "x-api-key": config.anthropic.apiKey }
141
- : {}),
147
+ ...(routed.credential.source === "per-model" ? { "x-api-key": routed.credential.apiKey ?? "" } : routeCredentialHeader(routeCredential)),
142
148
  };
143
149
  const want = maxOutputTokens ?? 1024;
144
150
  const maxTokens = Math.min(config.models[pick.catalogRef]?.maxTokens ?? want, want);
@@ -1,11 +1,11 @@
1
1
  import { type HookEntry, type HookEntryType, type HookEventName, type HooksDroppedPiece, type HooksDroppedPieceCode, type HooksRejection, type HooksRejectionCode } from "@sema-agent/settings-schema/hooks";
2
- import { type ConfigPath } from "@sema-agent/settings-schema";
2
+ import { type ConfigPath, type UrlCredential } from "@sema-agent/settings-schema";
3
3
  import { ENGINE_OWNED_HOOK_EVENTS } from "@sema-agent/settings-schema/hooks";
4
4
  import type { EngineDollar, ModRegistration } from "@sema-agent/core";
5
5
  import type { Logger } from "../observability/logger.js";
6
6
  import type { HookManagedUnrun, HookNoticeObservation } from "../fleet/fleet-bus.js";
7
7
  import { LIMIT_REASONS, type LimitMeasure } from "../limit-refusal.js";
8
- import { type UrlCredential, type UrlCredentialRefusal } from "../url-credential.js";
8
+ import { type UrlCredentialRefusal } from "../url-credential-refusal.js";
9
9
  import { type HookGroupSource } from "./hook-source.js";
10
10
  import { type RunnableCommandHookEntry } from "./command-spawn.js";
11
11
  /** 服务侧防线上限(契约本身不设量纲;不设界=单请求可塞任意大配置/任意长命令)。超界=校验错(fail-loud)。 */
@@ -414,7 +414,7 @@ export interface HooksUrlCredentialIssue {
414
414
  readonly credential: UrlCredential;
415
415
  }
416
416
  /**
417
- * fresh 提交面专用判据([ref]):配置里第一条「url 带凭据」的 http 钩子 —— userinfo,或名字在日志脱敏器凭据名表里的 query / fragment 参数(判官 `url-credential.ts` 一只,
417
+ * fresh 提交面专用判据([ref]):配置里第一条「url 带凭据」的 http 钩子 —— userinfo,或名字在日志脱敏器凭据名表里的 query / fragment 参数(判官契约包根的 `findUrlCredential` 一只,
418
418
  * MCP `transport.url` · A2A 对端 · 搜索后端 `endpoint` · 包源六址同读);没有 ⇒ undefined。这一座有为凭据设的位(条目的 `headers`,停驻任务的续跑上下文里只以封签存在),
419
419
  * url 却照原样进停驻上下文、日志与读面 —— 凭据只许走前者(`$NAME` 引用 + `allowedEnvVars` 让配置本身不携带密钥值,见 USAGE 9.5c)。
420
420
  * 入参是 {@link parseHooksConfig} 已校验过的配置:**按配置序**(事件 → 组 → 条目)遇到的第一条定结局;只看 `type:"http"` 条目(别的条目型没有 `url`)。
@@ -425,7 +425,7 @@ export interface HooksUrlCredentialIssue {
425
425
  export declare function hooksUrlCredentialIssue(config: RunnableHooksConfig): HooksUrlCredentialIssue | undefined;
426
426
  /**
427
427
  * {@link hooksUrlCredentialIssue} 的判决 → 拒句 + 机读位。`field` 是这一条 `url` 在请求体里的全坐标(`settings.hooks.<事件>[g].hooks[h].url`,与封签位、本族别的 `field` 同一种写法),
428
- * 出路指到同一条的 `headers`。机读位的形与 MCP / A2A / 搜索后端三座同一只铸点(`url-credential.ts`),所以**不**走上面 {@link buildHooksRefusal} 的 `field:"settings.hooks"` + `detail` 形 ——
428
+ * 出路指到同一条的 `headers`。机读位的形与 MCP / A2A / 搜索后端三座同一只铸点(`url-credential-refusal.ts`),所以**不**走上面 {@link buildHooksRefusal} 的 `field:"settings.hooks"` + `detail` 形 ——
429
429
  * 那一形按 `detail.reason` 分形、属于配置读者与 matcher 判据;「URL 带凭据」是跨座位的一个事实,消费端按 `reason` 穷举读一次。
430
430
  */
431
431
  export declare function buildHooksUrlCredentialRefusal(issue: HooksUrlCredentialIssue): UrlCredentialRefusal;
@@ -3,7 +3,7 @@ import { composeHostSubprocessEnv, hostSubprocessEnv } from "../server-secret-en
3
3
  import vm from "node:vm";
4
4
  import { hostShell, resolveHostShell, adoptHostForegroundChild, killTreeSoft, killTreeHard } from "../plugins/host-platform.js";
5
5
  import { classifyHooksConfig, DEFAULT_HOOK_TIMEOUT_SECONDS, HOOK_ENTRY_TYPES, HOOK_EVENTS, HOOK_EVENT_OWNER, HOOK_EVENT_MATCHER_FIELD, hookMatcherForm, hookMatcherSelects, interpolateHookEnvVars, } from "@sema-agent/settings-schema/hooks";
6
- import { formatConfigPath, outgoingPath } from "@sema-agent/settings-schema";
6
+ import { findUrlCredential, formatConfigPath, outgoingPath } from "@sema-agent/settings-schema";
7
7
  import { ENGINE_OWNED_HOOK_EVENTS } from "@sema-agent/settings-schema/hooks";
8
8
  import { describeToolCatalog } from "@sema-agent/core";
9
9
  import { hangClassic } from "./classic-stations.js";
@@ -17,7 +17,7 @@ import { canonicalJsonStringify } from "@sema-agent/core";
17
17
  import { ccPromptSystemFor, wrapCondition, parseCcVerdict, CC_EVALUATOR_MAX_OUTPUT_TOKENS } from "./cc-stop-prompt.js";
18
18
  import { ccAgentHookSystemFor } from "./cc-agent-hook-prompt.js";
19
19
  import { renderBranchTranscript } from "./branch-transcript.js";
20
- import { buildRequestUrlCredentialRefusal, findUrlCredential, urlCredentialHeaderExit } from "../url-credential.js";
20
+ import { buildRequestUrlCredentialRefusal, urlCredentialHeaderExit } from "../url-credential-refusal.js";
21
21
  import { HOOK_PHASES, HOOK_SOURCE_VOCABULARY_SENTENCE, hookPhaseOf, readHookGroupSource } from "./hook-source.js";
22
22
  import { commandLineChars, composeHookEnvLayer, hookPluginChars, planCommandSpawn, readHookArgs, readHookPlugin } from "./command-spawn.js";
23
23
  export const MAX_HOOK_ENTRIES_PER_EVENT = 32;
@@ -12,7 +12,7 @@ import { FILE_HISTORY_DISABLED_NO_RESTORE, fileHistoryRestoreConflict, fileHisto
12
12
  import * as facts from "../capability-facts.js";
13
13
  import { buildHooksRefusal, buildHooksUrlCredentialRefusal, parseHooksConfig, hooksMatcherIssue, hooksUrlCredentialIssue } from "../hooks/hook-runner.js";
14
14
  import { judgeFreshRequestWebSearch } from "../plugins/web-search.js";
15
- import { normalizeApproachNotice, skillToolListOk, unknownTaskAgentModelRef, validateTaskAgents } from "../spec-fields.js";
15
+ import { ATTACHMENT_BOOLEAN_KEYS, ATTACHMENT_KEYS, normalizeApproachNotice, skillToolListOk, unknownTaskAgentModelRef, validateTaskAgents } from "../spec-fields.js";
16
16
  import { allowSelectorWarningsOf, skillToolListsOverCap } from "../rule-entry-list.js";
17
17
  import { limitFacts, limitRefusal } from "../limit-refusal.js";
18
18
  import { fieldConflictFacts } from "../field-conflict.js";
@@ -78,6 +78,8 @@ function userSkillShapeIssue(item, index) {
78
78
  }
79
79
  if (skillCarriesRetiredManifest(s))
80
80
  return { message: SKILL_MANIFEST_RETIRED };
81
+ if (s["mods"] !== undefined)
82
+ return { message: "skill.mods is not a request key — skill registrations are code the deployment mounts, not request data (this server does not compile skill hooks: GET /v1/capabilities answers mods.skill_seat: false)" };
81
83
  for (const key of ["allowedTools", "disallowedTools"]) {
82
84
  if (s[key] !== undefined && !skillToolListOk(s[key]))
83
85
  return { message: `skill.${key} must be an array of strings (permission-rule spellings: a tool name, mcp__<server> / mcp__<server>__*, Bash(<prefix>:*), Read(//<dir>/**))` };
@@ -457,7 +459,7 @@ export function createAdmission(ctx) {
457
459
  {
458
460
  const inheritEnvIssue = inheritEnvFieldIssue(body);
459
461
  if (inheritEnvIssue) {
460
- sendError(res, 400, "request.field_invalid", inheritEnvIssue);
462
+ sendError(res, 400, "request.field_invalid", inheritEnvIssue.message, inheritEnvIssue.facts);
461
463
  return null;
462
464
  }
463
465
  }
@@ -618,9 +620,9 @@ export function createAdmission(ctx) {
618
620
  }
619
621
  }
620
622
  {
621
- const v = body.promptProfile;
622
- if (v !== undefined && v !== "simple" && v !== "classic") {
623
- sendError(res, 400, "request.field_invalid", 'promptProfile must be "simple" or "classic"');
623
+ const v = body.promptLean;
624
+ if (v !== undefined && typeof v !== "boolean") {
625
+ sendError(res, 400, "request.field_invalid", "promptLean must be a boolean");
624
626
  return null;
625
627
  }
626
628
  }
@@ -687,7 +689,8 @@ export function createAdmission(ctx) {
687
689
  if (body.attachments !== undefined) {
688
690
  const a = body.attachments;
689
691
  if (typeof a !== "object" || a === null || Array.isArray(a)) {
690
- sendError(res, 400, "request.field_invalid", "attachments must be an object { todoReminder?, todoReminderMode?, changedFiles?, budgetUsd?, backgroundTasks?, toolsDelta?, agentListing?, skillsListing?, mcpInstructions? }");
692
+ const attachmentKeyList = ATTACHMENT_KEYS.map((k) => `${k}?`).join(", ");
693
+ sendError(res, 400, "request.field_invalid", `attachments must be an object { ${attachmentKeyList} }`);
691
694
  return null;
692
695
  }
693
696
  const rec = a;
@@ -695,7 +698,7 @@ export function createAdmission(ctx) {
695
698
  sendError(res, 400, "request.field_invalid", 'attachments.planModeReminder was retired in core 7.39.0 — the engine now states plan posture itself whenever the permission mode is "plan" (first request, periodic reminders, exit frame); remove the key (send permissionMode "plan" for plan posture)');
696
699
  return null;
697
700
  }
698
- for (const k of ["todoReminder", "budgetUsd", "backgroundTasks", "toolsDelta", "agentListing", "skillsListing", "mcpInstructions"]) {
701
+ for (const k of ATTACHMENT_BOOLEAN_KEYS) {
699
702
  if (rec[k] !== undefined && typeof rec[k] !== "boolean") {
700
703
  sendError(res, 400, "request.field_invalid", `attachments.${k} must be a boolean`);
701
704
  return null;
@@ -1,5 +1,6 @@
1
1
  import { redactHead } from "../observability/run-terminal.js";
2
2
  const errText = (e) => redactHead(e instanceof Error ? e.message : String(e), 2000);
3
+ import { checkpointRevOf } from "@sema-agent/core";
3
4
  import { findParkOrigin } from "../parked-decide.js";
4
5
  import { decodeCheckpointScope } from "../security.js";
5
6
  import { hostDecisionFacts } from "../host-decision.js";
@@ -89,7 +90,7 @@ export function createApprovalSweeps(ctx) {
89
90
  const cp = await cs.get(token);
90
91
  if (!cp)
91
92
  return { token, parked: false, rev: undefined };
92
- const rev = cp.rev ?? 0;
93
+ const rev = checkpointRevOf(cp);
93
94
  if (!parkSources)
94
95
  return { token, parked: false, rev };
95
96
  const origin = await findParkOrigin({
@@ -120,7 +121,7 @@ export function createApprovalSweeps(ctx) {
120
121
  const cp = await cs.get(cardToken);
121
122
  if (!cp)
122
123
  return;
123
- if (cp.status !== "pending" || (cp.rev ?? 0) !== observedRev) {
124
+ if (cp.status !== "pending" || checkpointRevOf(cp) !== observedRev) {
124
125
  deps.logger?.warn?.("deny_sweep_policy_blocked_expire_skipped", { sessionId, skipReason: cp.status !== "pending" ? "not_pending" : "card_changed", ...blockedScalars(body) });
125
126
  return;
126
127
  }
@@ -177,7 +178,7 @@ export function createApprovalSweeps(ctx) {
177
178
  deps.logger?.warn?.("deny_sweep_stored_body_skipped", {
178
179
  count: replaySkipped.length,
179
180
  skipped: replaySkipped,
180
- note: "these expired approvals belong to tasks whose stored request this version does not replay (kind allow_list_reading: settings.permissions.allow written under an earlier reading; kind inert_tool_list: a tool-list entry (a skill disallowedTools, an agent definition's denyTools / allowTools or the request's excludeTools / allowTools) the engine reads as empty), so the SLA deny cannot be delivered. They stay suspended until the terminal backstop reaps them or someone cancels them; nothing was retried",
181
+ note: "these expired approvals belong to tasks whose stored request this version does not replay (skipped[].kind names the rule that refused each one; the resume paths log the same kinds with a reason per kind), so the SLA deny cannot be delivered. They stay suspended until the terminal backstop reaps them or someone cancels them; nothing was retried",
181
182
  });
182
183
  }
183
184
  }
@@ -8,7 +8,8 @@
8
8
  *
9
9
  * · 单用户 turnkey(`requirePrincipal !== true`,本仓 posture 判别式同一只)⇒ `global`:一台机一位超管;
10
10
  * · 多租 · 部署的 service 凭据 ⇒ `global`:部署自己的凭据是运维档(契约给「启动方自己的行为」—— `SETTINGS_SOURCE_CONTRACT.flagSettings` —— 的档),持它的前端为自己转发的内容负责;
11
- * 出示的 Bearer 就是 service 凭据时,哪怕它同时也被鉴权桥验成登录令牌,也按 service 凭据读(与凭据门派 `source` 同序:`dispatch.ts` 先认 service 凭据);
11
+ * 出示的 Bearer 就是 service 凭据时,哪怕它同时也被鉴权桥验成登录令牌,也按 service 凭据读 —— 这不是本表的判:来源只有一只判定次序(`verifiedIdentitySource`,
12
+ * service 凭据先;凭据门的 401 / 归因 / run 行身份元组读同一次的答案),本表只按来源词分档;
12
13
  * · 多租 · 中心登录令牌,scope 角色 ≥ 契约 `domainWriteRole("governance")` ⇒ `global`:能写 scope 治理域(autonomy / commandPolicy / approvalRequire,全组织的免问面)
13
14
  * 的角色,放宽自己这一 run 是它的子集;门槛读契约,不手抄角色词;
14
15
  * · 多租 · 其余(登录令牌角色低于它 / 不带 / 认不出;直连门 principal 令牌只证身份不证角色;没有验过的凭据)⇒ `project`:契约给非运维档作者的仓控来源的档,
@@ -1,7 +1,7 @@
1
1
  import { domainWriteRole, isAtLeast, isRole, memberAdmission, membersOf, roleAtLeast, USER_ROLES, } from "@sema-agent/settings-schema";
2
2
  import { entryProblem, entryProblemsFacts } from "../entry-problems.js";
3
3
  import { ssoVerifiedRole } from "../security.js";
4
- import { systemFor, verifiedIdentitySource } from "./principal-gate.js";
4
+ import { verifiedIdentitySource } from "./principal-gate.js";
5
5
  export function callerTrust(req, config) {
6
6
  if (config.requirePrincipal !== true)
7
7
  return { trust: "global", basis: "single_user" };
@@ -10,8 +10,6 @@ export function callerTrust(req, config) {
10
10
  case "service_token":
11
11
  return { trust: "global", basis: "service_credential" };
12
12
  case "sso": {
13
- if (systemFor(req, config) !== undefined)
14
- return { trust: "global", basis: "service_credential" };
15
13
  const role = ssoVerifiedRole(req);
16
14
  if (role === undefined || !isRole(role))
17
15
  return { trust: "project", basis: "sign_in_role_unrecognized" };