@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
@@ -13,6 +13,7 @@ export const DEVICE_OUTCOME_TO_FILE_ERROR = {
13
13
  invalid: "invalid",
14
14
  is_directory: "is_directory",
15
15
  liveness_no_output: "unknown",
16
+ name_too_long: "name_too_long",
16
17
  not_directory: "not_directory",
17
18
  not_found: "not_found",
18
19
  not_supported: "not_supported",
@@ -35,6 +36,7 @@ export const DEVICE_OUTCOME_TO_EXEC_ERROR = {
35
36
  invalid: "unknown",
36
37
  is_directory: "unknown",
37
38
  liveness_no_output: "liveness_no_output",
39
+ name_too_long: "unknown",
38
40
  not_directory: "unknown",
39
41
  not_found: "unknown",
40
42
  not_supported: "shell_unavailable",
@@ -123,6 +125,7 @@ export class RemoteDeviceExecutionEnv {
123
125
  cfg;
124
126
  homeDir;
125
127
  cdPath = "unknown";
128
+ withheldEnv = [];
126
129
  capabilities = { isolation: false, suspendable: false, canonicalPathAuthoritative: true };
127
130
  externalContentTarget = true;
128
131
  hostLocalPaths = false;
@@ -766,6 +769,7 @@ const OUTCOME_TO_REMOTE_ERROR = {
766
769
  invalid: "unknown",
767
770
  is_directory: "unknown",
768
771
  liveness_no_output: "liveness_no_output",
772
+ name_too_long: "unknown",
769
773
  not_directory: "unknown",
770
774
  not_found: "unknown",
771
775
  not_supported: "unsupported",
@@ -104,6 +104,9 @@ export declare class RemoteContainerExecutionEnv implements RemoteExecutionEnv,
104
104
  /** core 7.49.0 [ref]:shell 子进程真拿到的 `CDPATH` 条目 —— 本车道的命令跑在 e2b 沙箱里(模板镜像的 env),本类不读那份 env ⇒ `"unknown"`(core 契约:说不出就说 unknown,
105
105
  * 不许报一张没读过的空表;删除守卫因此对裸 `cd <相对名>` 之后的删除问人,而不是按「没有 CDPATH」放行)。 */
106
106
  readonly cdPath: "unknown";
107
+ /** core 7.56.0 [ref]:shell 子进程继承的环境里收不到的条目 —— 本车道 shell 的环境在沙箱里**构建**(本进程的 env 从不注入,只有引擎逐次交的 `env`
108
+ * 这条显式授予),没有一条是从本进程继承的 ⇒ `[]`(core 契约:「`[]` when its shell environment is built rather than inherited」)。 */
109
+ readonly withheldEnv: readonly [];
107
110
  private readonly cfg;
108
111
  private readonly sandboxApi;
109
112
  /** This lane's own liveness bound — what {@link commandBoundsOf} falls back to when a command's caller stated no bound. */
@@ -20,6 +20,7 @@ export class RemoteContainerExecutionEnv {
20
20
  cwd;
21
21
  homeDir;
22
22
  cdPath = "unknown";
23
+ withheldEnv = [];
23
24
  cfg;
24
25
  sandboxApi;
25
26
  laneLiveness;
@@ -18,6 +18,12 @@
18
18
  import { FileError, type ExecutionError, type RemoteExecutionError } from "@sema-agent/core";
19
19
  /** exec 层的错误码 → 文件层的码。只映射**有对应语义**的那些,其余落 `unknown`(诚实降级)。 */
20
20
  export declare function fileErrorFromExec(e: ExecutionError | RemoteExecutionError, path?: string): FileError;
21
+ /**
22
+ * core 7.56.0 [ref]:`ENAMETOOLONG` 的**一只读法**(本文件的 stderr 分类器与 host 车道的 errno 映射同调)—— 路径有一段超过 NAME_MAX(按 UTF-8 字节量)⇒
23
+ * `name_too_long`:没有目录装得下这个名字,引擎读站把它读作缺席(与 `not_found` 同读);段都短、只是整条超 PATH_MAX ⇒ `unknown`(那种文件可能存在,从下层目录够得着)。
24
+ * 没有路径可判 ⇒ `unknown`。与 core `NodeExecutionEnv` 同判(按 `/` 与 `\` 切段)。
25
+ */
26
+ export declare function nameTooLongCode(p: string | undefined): "name_too_long" | "unknown";
21
27
  /**
22
28
  * shell 命令 exit≠0 时把 **stderr** 分类成 `FileError` 的共享分类器([ref] B6 R2 裁决:k8s 形=正形)。
23
29
  *
@@ -29,7 +35,8 @@ export declare function fileErrorFromExec(e: ExecutionError | RemoteExecutionErr
29
35
  * 1. 命令缺失形(`command not found` / `applet not found` / `: not found`)→ `unknown` —— 工具不存在
30
36
  * 不是文件不存在;probe 族的 not_found fallback 绝不能吞它。
31
37
  * 2. 完整硬失败(EIO/ELOOP/ENAMETOOLONG/ENOSPC)→ `unknown` —— 同 k8s 原注:真错不被 read-op 的
32
- * not_found fallback 吞掉。
38
+ * not_found fallback 吞掉。**例外**(core 7.56.0 [ref]):`ENAMETOOLONG` 且路径有一段超过 NAME_MAX ⇒ `name_too_long`
39
+ * ({@link nameTooLongCode},一只读法,host 车道的 errno 映射同调)—— 那个名字没有目录装得下,是一种「不存在」,不是硬失败。
33
40
  *
34
41
  * `fallback` 由站点显式给:probe 族(readlink/realpath/stat——"它在吗"类问题)传 `not_found`
35
42
  * (空 stderr + exit≠0 的主导原因就是缺文件);mutate 族(mkdir/rm/mktemp)传 `unknown`(诚实降级)。
@@ -3,11 +3,17 @@ export function fileErrorFromExec(e, path) {
3
3
  const code = e.code === "aborted" ? "aborted" : "unknown";
4
4
  return new FileError(code, e.message, path, e);
5
5
  }
6
+ const NAME_MAX_BYTES = 255;
7
+ export function nameTooLongCode(p) {
8
+ return p !== undefined && p.split(/[\\/]/).some((part) => Buffer.byteLength(part, "utf8") > NAME_MAX_BYTES) ? "name_too_long" : "unknown";
9
+ }
6
10
  export function classifyFsStderr(stderr, p, fallback = "unknown") {
7
11
  const msg = stderr.trim();
8
12
  if (/command not found|applet not found|:\s+not found\s*$/im.test(msg))
9
13
  return new FileError("unknown", msg, p);
10
- if (/input\/output error|too many levels|file name too long|no space left/i.test(msg))
14
+ if (/file name too long/i.test(msg))
15
+ return new FileError(nameTooLongCode(p), msg, p);
16
+ if (/input\/output error|too many levels|no space left/i.test(msg))
11
17
  return new FileError("unknown", msg, p);
12
18
  if (/no such file/i.test(msg))
13
19
  return new FileError("not_found", msg, p);
@@ -1,4 +1,4 @@
1
- import { FileError, type InheritEnvPolicy, ExecutionError, RemoteExecutionError, SchedulerError, type SchedulerCapability, type ScheduledIntent, type SchedulerContext, type ScheduledTaskId, type ScheduledTaskSummary, type ExecutionEnv, type RemoteExecutionEnv, type WorkspaceHandle, type FileInfo, type Result, type SymlinkChain, type BoundFileObject, type OutputChunk, type ExecStreamOptions, type RemoteConnectConfig, type SnapshotId, type SessionToken, type VmLifecycleOptions, type ExecutionEnvFactory, BackgroundShellError, type BackgroundShellCapability, type BackgroundShellId, type BackgroundHardKillOutcome, type BackgroundPoll, type BackgroundSpawnOptions } from "@sema-agent/core";
1
+ import { FileError, type InheritEnvPolicy, ExecutionError, RemoteExecutionError, SchedulerError, type SchedulerCapability, type ScheduledIntent, type SchedulerContext, type ScheduledTaskId, type ScheduledTaskSummary, type ExecutionEnv, type RemoteExecutionEnv, type WorkspaceHandle, type FileInfo, type Result, type SymlinkChain, type BoundFileObject, type OutputChunk, type ExecStreamOptions, type RemoteConnectConfig, type SnapshotId, type SessionToken, type VmLifecycleOptions, type ExecutionEnvFactory, BackgroundShellError, type BackgroundShellCapability, type BackgroundShellId, type BackgroundHardKillOutcome, type BackgroundPoll, type BackgroundSpawnOptions, type SecretEnvFinding } from "@sema-agent/core";
2
2
  /** Options accepted by `ExecutionEnv.exec` (core does not re-export the type; derive it from the seam). */
3
3
  type ExecOpts = Parameters<ExecutionEnv["exec"]>[1];
4
4
  /** SIGTERM → grace → SIGKILL (no host isolation). 🔴 宽限的**唯一属主**:本 driver 的 `kill` 梯子用它排升级定时器;会话级收敛
@@ -101,6 +101,12 @@ export declare class RemoteHostExecutionEnv implements RemoteExecutionEnv, Sched
101
101
  * {@link hostShell}(win32 上未落定同步抛 —— 修前每条 Bash 的策略链都因此被拒)。
102
102
  */
103
103
  get cdPath(): readonly string[];
104
+ /**
105
+ * core 7.56.0 [ref]:shell 子进程继承的环境里**收不到**的条目(名 + 规则,从不带值)—— 与 {@link cdPath} 同一只组合的读面
106
+ * (`server-secret-env.ts` 的 `withheldFromHostSubprocess`:继承组合扣下的发现,减去 `cfg.env` 这条显式授予重供的键)。逐命令的 `options.env`
107
+ * 是引擎自己交的显式授予,它知道(core KL-1963-b 同一残余)。只读:不披露、不计数、不碰 shell。
108
+ */
109
+ get withheldEnv(): readonly SecretEnvFinding[];
104
110
  private readonly workspaceDir;
105
111
  private readonly cfg;
106
112
  /** Workspace created on disk (lazily, on first use). */
@@ -11,7 +11,8 @@ import { hostBackgroundShellEnabled, hostExecSpoolEnabled } from "../config.js";
11
11
  import { IS_WIN32, resolveHostShell, hostShell, pinHostShell, spawnGroupOptions, killTreeHard, killTreeSoft, hardKillGroupNow, collapseWin32EnvKeys, adoptHostForegroundChild } from "./host-platform.js";
12
12
  import { BackgroundShellManager, seedMemStream, feedMemStream, drainMemStream } from "./background-shell-support.js";
13
13
  import { FileError, NodeExecutionEnv, inheritEnvPolicyProblem, ExecutionError, RemoteExecutionError, RollingTailBuffer, walkSymlinkChain, markTruncated, SchedulerError, BackgroundShellError, } from "@sema-agent/core";
14
- import { composeHostSubprocessEnv, hostSubprocessEnv } from "../server-secret-env.js";
14
+ import { composeHostSubprocessEnv, hostSubprocessEnv, withheldFromHostSubprocess } from "../server-secret-env.js";
15
+ import { nameTooLongCode } from "./remote-env-file-error.js";
15
16
  import { trackEphemeralHostWorkspace, untrackEphemeralHostWorkspace } from "./host-workspace-registry.js";
16
17
  const PROVIDER = "host";
17
18
  const DEFAULT_COMMAND_TIMEOUT_MS = 30 * 60_000;
@@ -61,6 +62,9 @@ export class RemoteHostExecutionEnv {
61
62
  const value = this.childEnv(undefined, undefined).CDPATH;
62
63
  return value === undefined || value === "" ? [] : value.split(":");
63
64
  }
65
+ get withheldEnv() {
66
+ return withheldFromHostSubprocess({ policy: this.cfg.inheritEnv, allow: [] }, this.cfg.env);
67
+ }
64
68
  workspaceDir;
65
69
  cfg;
66
70
  prepared = false;
@@ -1331,6 +1335,8 @@ export class RemoteHostExecutionEnv {
1331
1335
  return new FileError("not_directory", msg, p);
1332
1336
  if (code === "EINVAL")
1333
1337
  return new FileError("invalid", msg, p);
1338
+ if (code === "ENAMETOOLONG")
1339
+ return new FileError(nameTooLongCode(p), msg, p);
1334
1340
  return new FileError("unknown", msg, p);
1335
1341
  }
1336
1342
  }
@@ -110,9 +110,11 @@ export interface K8sEnvConfig extends LaneHomeConfig {
110
110
  cacheMisses?: CacheMissMemory;
111
111
  /** Operator log seat (the e2b adapter's shape): `workspace_snapshot_failed` / `workspace_snapshot_prune_failed` /
112
112
  * `workspace_space_unavailable` / `workspace_space_unreadable_occupant` / `workspace_commit_abandoned` / `workspace_latest_dangling` /
113
- * `workspace_restore_failed` / `workspace_cache_fresh` / `workspace_cache_unavailable`. */
113
+ * `workspace_restore_failed` / `workspace_snapshot_bucket_missing` / `workspace_cache_fresh` / `workspace_cache_unavailable`, and — at `error` level, on a seat
114
+ * that has one (the deployment's logger does; the seat itself is optional, and the counter behind the line does not depend on it) — `sandbox_pod_delete_failed`. */
114
115
  logger?: {
115
116
  warn(event: string, fields?: Record<string, unknown>): void;
117
+ error?(event: string, fields?: Record<string, unknown>): void;
116
118
  };
117
119
  /** Run-end outcome seat — called once per `destroy()` that attempted a space snapshot (the factory's caller binds it
118
120
  * to the run, so the run's terminal frame can carry `workspaceSnapshot: "failed"`). */
@@ -130,13 +132,39 @@ export interface K8sEnvConfig extends LaneHomeConfig {
130
132
  podSpecPatch?: PodSpecPatch;
131
133
  /** RFC B5 (sema-internal server/docs/design/ENV-SELECT-AND-REGION-SOURCE.md 抽象点②): operator-trusted env injected into the
132
134
  * sandbox container (e.g. `SEMA_PKG_SOURCE=cn|global` — the runtime package-source selector the image's
133
- * pkg-source.sh hook materializes at start). Deployment config, NEVER task-controlled. This is the pod's ONE container-env
134
- * seat: the region package-source set AND the deployer-named forwarding (`K8S_SANDBOX_ENV` keys, original values) arrive
135
- * here already merged by the boot assembly (explicit names win). Values go into `containers[0].env[]` and nowhere else —
136
- * never a command string, the workspace or a snapshot. Absent = the pod is byte-identical to today. */
135
+ * pkg-source.sh hook materializes at start). Deployment config, NEVER task-controlled. The pod's NON-SECRET env seat: the region
136
+ * package-source set (and the cache env layered under it) — values that are no secret go into `containers[0].env[]` as `{ name, value }`.
137
+ * Never a command string, the workspace or a snapshot. Absent = no such entries. */
137
138
  podEnv?: Record<string, string>;
139
+ /** The pod's SECRET env seat: the deployer-named forwarding (`K8S_SANDBOX_ENV` keys, original values; disjoint from {@link podEnv} — the boot
140
+ * assembly drops a collided name from the non-secret seat, explicit wins; a name in both is read here). The values reach the agent container
141
+ * ONLY through this pod's own Secret: the pod spec carries `valueFrom.secretKeyRef` and no value; the Secret is created after the pod, owned by
142
+ * it (`ownerReferences`, `immutable`) — a Secret that cannot be created ⇒ the pod is deleted and the connect refused, never a plaintext fallback.
143
+ * Absent / empty ⇒ no Secret, the pod as without it. */
144
+ podSecretEnv?: Record<string, string>;
145
+ /** The server run that owns this env — the TOP-LEVEL run's id (its task id), handed in by the per-run binding (`boot/execution-env.ts`), which
146
+ * hands none to a delegated child, a run the service starts for itself, or a run without a task id. Carried as the pod label `sema.io/run`
147
+ * (the reaper's key: a pod whose run is over is removed); a value that is no label value is not carried. Absent ⇒ the pod names no run. */
148
+ runId?: string;
149
+ /**
150
+ * The member git-credential broker seat — present ⇔ the per-run binding found the plane on and this run a member's (`sso`) run
151
+ * (`sandbox-git-plane.ts` `sandboxBrokerSeatOf`). The pod then carries the broker container (`containers[1]`: the fixed program of
152
+ * `broker/constants.ts`, image = `image`, the securityContext written key by key, an exec readiness probe), its lease volume (a SECOND
153
+ * per-pod Secret, `sema.io/sandbox-lease` — mutable, owned by the pod, only `broker.json`; created after the pod holding a placeholder lease
154
+ * in which every entry is withdrawn), `shareProcessNamespace: false`, and on the agent container one `GIT_CONFIG_*` insteadOf route per
155
+ * origin (`origins` = the pod's origin table, in order — the same table every lease write is stamped from). The connect waits for the
156
+ * broker container to be ready; any failure on that path deletes the pod and refuses the connect. A deployment patch that could reach
157
+ * the broker refuses the connect before any pod is created. Absent ⇒ the pod as without it (byte-identical).
158
+ */
159
+ sandboxBroker?: {
160
+ readonly image: string;
161
+ readonly origins: readonly string[];
162
+ };
138
163
  }
164
+ import { type SandboxSecretSeatKind, type SandboxSecretVerb } from "./k8s-exec-protocol.js";
139
165
  export { type PodSpecPatch, applyPodSpecPatch } from "./k8s-exec-protocol.js";
166
+ import { type SandboxPodApi, type SandboxPodListing } from "./k8s-pod-reaper.js";
167
+ import { type SandboxLeaseEntryInput } from "../sandbox-git-lease.js";
140
168
  type ConnectResult = {
141
169
  ok: true;
142
170
  value: WorkspaceHandle;
@@ -154,11 +182,14 @@ export interface ExecSocket {
154
182
  * Test seam ([ref] §9.3 fault-injection): inject the REST `request` and/or the exec-socket factory, so pod
155
183
  * lifecycle, retry policy, channel framing and liveness are deterministically testable without a cluster.
156
184
  */
185
+ /** One control-plane request's options: its wall-clock, its abort, and the body's media type (default `application/json`; a merge-patch says so). */
186
+ export interface K8sRequestOptions {
187
+ timeoutMs?: number;
188
+ signal?: AbortSignal;
189
+ contentType?: string;
190
+ }
157
191
  export interface K8sEnvDeps {
158
- request?: (method: string, apiPath: string, body?: unknown, opts?: {
159
- timeoutMs?: number;
160
- signal?: AbortSignal;
161
- }) => Promise<{
192
+ request?: (method: string, apiPath: string, body?: unknown, opts?: K8sRequestOptions) => Promise<{
162
193
  status: number;
163
194
  json: unknown;
164
195
  }>;
@@ -229,6 +260,35 @@ export declare function errorMessageOf(e: unknown): string;
229
260
  export { exitCodeFromStatus } from "./k8s-exec-protocol.js";
230
261
  /** The sandbox namespace when `K8S_NAMESPACE` is unset (the one spelling: the adapter and the boot's egress line read it). */
231
262
  export declare const K8S_SANDBOX_NAMESPACE_DEFAULT = "sandboxes";
263
+ /**
264
+ * The boot reading of the sandbox Secret seat, a closed set: `granted` — every verb allowed · `denied` — the API answered "not allowed" for these
265
+ * verbs (a definite answer; it wins over a verb that could not be asked) · `unverified` — some verb could not be asked (the request failed, the
266
+ * review itself was refused, the answer had no `status.allowed`) and none was denied.
267
+ */
268
+ export type SandboxSecretSeat = {
269
+ readonly state: "granted";
270
+ } | {
271
+ readonly state: "denied";
272
+ readonly verbs: SandboxSecretVerb[];
273
+ } | {
274
+ readonly state: "unverified";
275
+ readonly detail: string;
276
+ };
277
+ /** Where a pod's lease lives and which origin table it was built with — what {@link writeSandboxLease} needs (read it from {@link RemoteK8sExecutionEnv.sandboxLeaseRef}). */
278
+ export interface SandboxLeaseRef {
279
+ readonly namespace: string;
280
+ readonly podName: string;
281
+ readonly leaseSecretName: string;
282
+ readonly origins: readonly string[];
283
+ }
284
+ /** One lease write's outcome (closed set): written · refused before sending (the broker would refuse it) · refused by the API · the Secret is gone (so is its pod) · any other failure. */
285
+ export type SandboxLeaseWrite = {
286
+ readonly ok: true;
287
+ } | {
288
+ readonly ok: false;
289
+ readonly code: "lease_invalid" | "auth_failed" | "gone" | "write_failed";
290
+ readonly message: string;
291
+ };
232
292
  export declare class RemoteK8sExecutionEnv implements RemoteExecutionEnv, BackgroundShellCapability {
233
293
  /**
234
294
  * 🔴 **[ref] / core 7.20.0([ref])`canonicalPathAuthoritative: true`** —— 本适配器的 `canonicalPath`
@@ -250,6 +310,8 @@ export declare class RemoteK8sExecutionEnv implements RemoteExecutionEnv, Backgr
250
310
  /** Cluster-internal pod address, captured when the pod reaches Running — the LSP `getHost` surface.
251
311
  * Lifecycle mirrors podName exactly (set on connect, cleared on suspend/destroy/dead-reconnect). */
252
312
  private podIP?;
313
+ /** The broker lease seat of the pod this env holds (set with {@link podName}; read through {@link sandboxLeaseRef}). */
314
+ private leaseRef?;
253
315
  private destroyed;
254
316
  /** Set after a successful resumeVM so workspaceHandle() carries the snapshot it was restored from. */
255
317
  private handleSnapshotId?;
@@ -274,6 +336,9 @@ export declare class RemoteK8sExecutionEnv implements RemoteExecutionEnv, Backgr
274
336
  /** core 7.49.0 [ref]:shell 子进程真拿到的 `CDPATH` 条目 —— 本车道的命令跑在 pod 里(镜像与 pod spec 的 env),本类不读那份 env ⇒ `"unknown"`(core 契约:说不出就说 unknown,
275
337
  * 不许报一张没读过的空表;删除守卫因此对裸 `cd <相对名>` 之后的删除问人,而不是按「没有 CDPATH」放行)。 */
276
338
  readonly cdPath: "unknown";
339
+ /** core 7.56.0 [ref]:shell 子进程继承的环境里收不到的条目 —— 本车道 shell 的环境在 pod 里**构建**(本进程的 env 从不注入,只有引擎逐次交的 `env`
340
+ * 这条显式授予),没有一条是从本进程继承的 ⇒ `[]`(core 契约:「`[]` when its shell environment is built rather than inherited」)。 */
341
+ readonly withheldEnv: readonly [];
277
342
  private readonly cfg;
278
343
  private readonly deps;
279
344
  /** The known occupant's incarnation (`undefined` = this run has no known occupant: a delegated child, an unread session, a direct construction) — the
@@ -295,6 +360,8 @@ export declare class RemoteK8sExecutionEnv implements RemoteExecutionEnv, Backgr
295
360
  private readonly onWorkspaceSnapshot?;
296
361
  private readonly cacheMisses?;
297
362
  constructor(config: K8sEnvConfig, deps?: K8sEnvDeps);
363
+ /** The lease seat of the pod this env holds now — `undefined` without a broker seat or without a pod (the server's lease writes follow it: a resumed env holds a new pod and a new seat). */
364
+ get sandboxLeaseRef(): SandboxLeaseRef | undefined;
298
365
  /** 166-T2 — ExecutionEnv 寿命声明:pod `activeDeadlineSeconds = ceil(timeoutMs/1000)` 是平台真硬死线
299
366
  * (k8s 到点杀 pod,无 keepalive 续期机制)⇒ 恒声明,core 在死线−60s 处 suspend(基建合格)或响亮
300
367
  * 终局(env.lifetime_expired)。`lifetimeStartedAt` 有意不声明:core 只在 prepare 期读一次,lazy-connect
@@ -311,8 +378,8 @@ export declare class RemoteK8sExecutionEnv implements RemoteExecutionEnv, Backgr
311
378
  * Connect = the workspace SPACE's restore point. Space lane open ⇒ first wait out a commit still in flight
312
379
  * ({@link awaitSpaceCommit}: the run store's commit row), then read `<prefix>/<incarnation>/space/latest`: present ⇒
313
380
  * restore it through {@link restoreSnapshot} (the one tar download, shared with `resumeVM`; an archive that is gone ⇒
314
- * loud `workspace_latest_dangling`, the pointer deleted, an empty workspace); absent (404) ⇒ a fresh pod; a read that
315
- * FAILS ⇒ a loud `connect_failed` — never a silent fresh workspace (a run that believes it resumed while it did not is
381
+ * loud `workspace_latest_dangling`, the pointer deleted, an empty workspace); absent (404 — the key, with the bucket there) ⇒ a fresh pod; a read that
382
+ * FAILS ⇒ a loud `connect_failed` — a 404 `NoSuchBucket` included ({@link refuseMissingBucket}) — never a silent fresh workspace (a run that believes it resumed while it did not is
316
383
  * the worst form). Once the pod holds the workspace, this env arms its fence seat (its destroy will commit).
317
384
  * Persistence off / no store ⇒ a fresh pod, exactly as before. Persistence on but no such session (the occupant absent) ⇒ a
318
385
  * fresh pod and one `workspace_space_unavailable` line (no restore by any other key). The occupant read FAULTED ⇒ the same
@@ -410,6 +477,15 @@ export declare class RemoteK8sExecutionEnv implements RemoteExecutionEnv, Backgr
410
477
  * same merge `createPod` applies). A read that is refused / fails / times out is a `unreadable` gap, never a guess. Never throws.
411
478
  */
412
479
  egressPolicyGaps(): Promise<SandboxEgressGap[]>;
480
+ /**
481
+ * The boot reading of one sandbox Secret seat ({@link SandboxSecretSeat}): one SelfSubjectAccessReview per verb of that seat's row in {@link SANDBOX_SECRET_SEAT_VERBS}
482
+ * on `secrets` in this env's namespace. An answer with `status.allowed: false` is a denial (RBAC never answers `denied: true` — "no rule allows
483
+ * it" IS its refusal); a failed request, a refused review or an answer without a boolean `status.allowed` is a verb not asked. The verbs are
484
+ * asked at once (the boot waits one control-plane bound, not four). Never throws.
485
+ */
486
+ secretSeatReading(seat: SandboxSecretSeatKind): Promise<SandboxSecretSeat>;
487
+ /** The sandbox pods of this env's namespace (selected by the identity labels), read for the reaper ({@link createSandboxPodApi}). Throws on a failed / refused listing. */
488
+ listSandboxPods(): Promise<SandboxPodListing[]>;
413
489
  /** The one spelling of "the reclaim call's deadline passed" — both halves of the reclaim (volume and objects) say it with this. */
414
490
  private reclaimDeadlinePassed;
415
491
  /** The cache volume could not be had: counted (`recordFailOpen`) and one operator line — once per env. */
@@ -417,6 +493,34 @@ export declare class RemoteK8sExecutionEnv implements RemoteExecutionEnv, Backgr
417
493
  /** Create one pod (with the cache volume when given) and wait for it to run. A {@link CacheMiss} = a pod carrying the
418
494
  * volume did not become ready (its claim unbound past the bind deadline, or bound and still not ready) — already deleted. */
419
495
  private createPod;
496
+ /**
497
+ * This pod's own Secret — the secret env seat ({@link K8sEnvConfig.podSecretEnv}): created AFTER the pod, owned by it (`ownerReferences` → the
498
+ * pod's uid, `blockOwnerDeletion: false` — the cluster's garbage collector removes it with the pod), `immutable`, `data["env.<NAME>"]` = the
499
+ * value (base64). The caller deletes the pod on any refusal: no uid to bind (`connect_failed`), refused (401 / 403 ⇒ `auth_failed`, not
500
+ * retried), any other answer or a failed request (`connect_failed`). A refusal never carries a value: the API's text is scrubbed of every value
501
+ * (raw and base64) before it enters the sentence.
502
+ */
503
+ private createPodSecret;
504
+ /**
505
+ * This pod's lease Secret — the member-credential broker's seat ({@link K8sEnvConfig.sandboxBroker}): created after the pod, owned by it
506
+ * (the same `ownerReferences` as the env Secret), NOT immutable (the server rewrites the lease: {@link writeSandboxLease}), one data key
507
+ * `broker.json` = the placeholder lease. Refusals as for the env Secret; the caller deletes the pod on any of them.
508
+ */
509
+ private createLeaseSecret;
510
+ /**
511
+ * One Secret owned by this pod (`ownerReferences` → its uid, `blockOwnerDeletion: false`; the cluster's garbage collector removes it with
512
+ * the pod). No uid to bind ⇒ `connect_failed`; refused (401 / 403) ⇒ `auth_failed`; any other answer or a failed request ⇒ `connect_failed`.
513
+ * A refusal never carries a value: the API's text is scrubbed of every `hidden` string before it enters the sentence.
514
+ */
515
+ private createOwnedSecret;
516
+ /**
517
+ * Rewrite one pod's lease (the server's ONLY lease write — {@link writeSandboxLease}): the file is built by the one lease builder from the
518
+ * pod's origin table (fresh `leaseId` per ready entry, the broker's own parser judges it — a file the broker would refuse is never sent) and
519
+ * lands as a merge-patch of `broker.json` on the pod's lease Secret. Every failure is typed, says one operator line
520
+ * (`sandbox_lease_write_failed`), carries no credential (the API's text is scrubbed of every secret and of the encoded file), and falls
521
+ * back to nothing: the broker keeps the lease it has, which lapses on its own clock.
522
+ */
523
+ writeLease(ref: SandboxLeaseRef, entries: readonly SandboxLeaseEntryInput[]): Promise<SandboxLeaseWrite>;
420
524
  /**
421
525
  * Build a validated, presigned URL for a snapshot object of either lane (see {@link SnapshotTarget}) — the ONE place a
422
526
  * snapshot object key is spelled, and the one place each lane's partition is chosen (park = the session id, space = the
@@ -425,10 +529,13 @@ export declare class RemoteK8sExecutionEnv implements RemoteExecutionEnv, Backgr
425
529
  * charset-validated upstream, so each path segment is allowlisted here (`^[A-Za-z0-9][A-Za-z0-9._-]*$`) before it enters
426
530
  * the object key: a segment of `..` / `../x` / one containing `/` would otherwise let one tenant's snapshot key normalize into
427
531
  * another tenant's prefix (cross-tenant read on resume / clobber on suspend). The space partition (a minted v4 uuid) goes
428
- * through the same one allowlist. Returns a typed error instead of signing a traversing key. Folds the old
532
+ * through the same one allowlist ({@link SNAPSHOT_KEY_SEGMENT}); the key prefix is a `/`-separated path of the same segments
533
+ * ({@link snapshotKeyPrefixProblem}, the rule the config loader refuses boot with). Returns a typed error instead of signing a traversing key. Folds the old
429
534
  * snapshotKey()+s3Presign() pair so the two call sites can't diverge.
430
535
  */
431
536
  private presignSnapshot;
537
+ /** The key prefix of every snapshot object this env signs — the ONE reading of `keyPrefix` (unset ⇒ the default); its form is judged in {@link presignSnapshot}. */
538
+ private snapshotKeyPrefix;
432
539
  /** A lane's partition prefix inside the bucket — the ONE place it is spelled (`presignSnapshot` signs under it; the reclaim reads the listing against it).
433
540
  * The partition segment is validated by `presignSnapshot` before a URL is signed. */
434
541
  private snapshotBase;
@@ -456,9 +563,19 @@ export declare class RemoteK8sExecutionEnv implements RemoteExecutionEnv, Backgr
456
563
  /** Worker-side object-store request, bounded by the control-plane RPC wall-clock — or a tighter caller deadline — and
457
564
  * the caller's abort. */
458
565
  private storeFetch;
459
- /** Read one space pointer object: its trimmed body, or `undefined` = absent (404); any other failure is a typed
566
+ /** Read one space pointer object: its trimmed body, or `undefined` = absent (404 — the bucket is there, the key is not); a 404 that says
567
+ * `NoSuchBucket` is NOT absence — the bucket itself is missing, and the run is refused ({@link refuseMissingBucket}); any other failure is a typed
460
568
  * `connect_failed` naming the pointer. */
461
569
  private readPointer;
570
+ /**
571
+ * The store answered the `latest` read with `404 NoSuchBucket`: the workspace snapshot bucket does not exist, so this space can be neither restored
572
+ * nor saved — a run started on it would work on an empty /workspace and lose everything it wrote. The env's refusal ({@link holdRefusal}), in the one
573
+ * space-read failure form ({@link spaceReadFailed}), naming the bucket and the knob that picks it; one `workspace_snapshot_bucket_missing{space, bucket, code, effect}`
574
+ * line per env (the refusal stands until destroy: later connects and operations answer it without another read or line; a retry of the run builds a fresh env, which
575
+ * asks the store afresh — a bucket created in between is found). The boot probe (`snapshot-bucket-presence.ts`) refuses a boot where the bucket is already missing;
576
+ * this is the same judgement ({@link isNoSuchBucketAnswer}) for a bucket that went missing afterwards or that the probe could not prove either way.
577
+ */
578
+ private refuseMissingBucket;
462
579
  /** Read the space's `latest` pointer. The body's shape is checked where it is used — restoreSnapshot → presignSnapshot
463
580
  * (the one segment check). */
464
581
  private readLatest;
@@ -571,7 +688,20 @@ export declare class RemoteK8sExecutionEnv implements RemoteExecutionEnv, Backgr
571
688
  error: RemoteExecutionError;
572
689
  }>;
573
690
  reconnect(_sessionToken: SessionToken): Promise<ConnectResult>;
574
- private deletePod;
691
+ /**
692
+ * Delete one pod — the ONE request path of "delete a sandbox pod" (the run-end delete, every refusal / reconnect clean-up, and the reaper's face: no grace).
693
+ * Resolves `"deleted"` (2xx) or `"gone"` (404: the pod never was / is already gone); throws {@link PodDeleteRefused} on any other answer and the request's own error on a transport failure.
694
+ */
695
+ deletePod(name: string): Promise<"deleted" | "gone">;
696
+ /**
697
+ * Give up the pod a refused connect had already created. The refusal is the caller's answer; the delete is the clean-up behind it — and a clean-up that FAILS leaves
698
+ * the pod, and the Secret(s) it owns (the deployer-named env values / the lease placeholder: data at rest that no connection carries), in the sandbox namespace until
699
+ * the pod reaper's backstop reaches them. That is said, not swallowed — through the ONE reporter the reaper's own delete step shares
700
+ * ({@link reportPodDeleteFailed}: the F-class counter `server.sandbox-pod.delete-failed` and one error line naming the pod, the namespace, why the pod was being
701
+ * given up and how the delete failed (`http_<status>` / `request_failed`) — never a value, never the API's own text).
702
+ * Never throws: the refusal the caller goes on to return stays the original one.
703
+ */
704
+ private discardRefusedPod;
575
705
  /**
576
706
  * Delete the sandbox pod. Idempotent, never throws. Space lane open and a pod exists ⇒ FIRST the run-end space
577
707
  * snapshot ({@link persistWorkspace}) — after the pod's processes are confirmed stopped, the commands still in flight having ended or been cut first ({@link quiesce}); from the
@@ -753,6 +883,16 @@ export declare function createSpaceReclaimer(config: K8sEnvConfig, deps?: K8sEnv
753
883
  * nodes that join after boot are read at the next boot. Never throws (a read failure is an `unreadable` gap).
754
884
  */
755
885
  export declare function checkSandboxEgressPolicy(config: K8sEnvConfig, deps?: K8sEnvDeps): Promise<SandboxEgressGap[]>;
886
+ /** The boot reading of one sandbox Secret seat for this k8s config ({@link RemoteK8sExecutionEnv.secretSeatReading}; a control-plane env, no pod). Never throws. */
887
+ export declare function readSandboxSecretSeat(config: K8sEnvConfig, seat: SandboxSecretSeatKind, deps?: K8sEnvDeps): Promise<SandboxSecretSeat>;
888
+ /**
889
+ * The server's one lease writer for a pod that carries the member-credential broker ({@link RemoteK8sExecutionEnv.writeLease}): `ref` is the
890
+ * pod's lease seat ({@link RemoteK8sExecutionEnv.sandboxLeaseRef}), `entries` one per origin of its table. A control-plane env, no pod.
891
+ */
892
+ export declare function writeSandboxLease(config: K8sEnvConfig, ref: SandboxLeaseRef, entries: readonly SandboxLeaseEntryInput[], deps?: K8sEnvDeps): Promise<SandboxLeaseWrite>;
893
+ /** The reaper's narrow face onto the sandbox namespace (list by identity labels, delete one) — a control-plane env, no pod, built at first use
894
+ * (as the space reclaimer builds its envs per call: the boot never constructs an env just to hold this face). */
895
+ export declare function createSandboxPodApi(config: K8sEnvConfig, deps?: K8sEnvDeps): SandboxPodApi;
756
896
  /**
757
897
  * `ExecutionEnvFactory` for the k8s pod-sandbox backend — one fresh (unconnected) env per task; the pod is
758
898
  * created lazily on connect and deleted by `destroy()` (Runner-owned lifetime; `activeDeadlineSeconds` is the