@sema-agent/server 7.125.1 → 7.127.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 (275) hide show
  1. package/MIGRATION.md +229 -2
  2. package/README.md +2 -2
  3. package/README.zh-CN.md +2 -2
  4. package/USAGE.md +346 -145
  5. package/deploy/sema-up/README.md +1 -1
  6. package/deploy/sema-up/chart/templates/networkpolicy-sandbox.yaml +57 -0
  7. package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +32 -1
  8. package/deploy/sema-up/chart/templates/server-v4pro.yaml +3 -2
  9. package/deploy/sema-up/chart/templates/server.yaml +2 -1
  10. package/deploy/sema-up/chart/values.yaml +22 -0
  11. package/deploy/sema-up/cluster-up.sh +10 -10
  12. package/deploy/sema-up/kube-up.sh +20 -13
  13. package/deploy/sema-up/lib/dataroot.sh +1 -1
  14. package/deploy/sema-up/lib/envf.sh +5 -5
  15. package/deploy/sema-up/lib/flagshape.sh +5 -5
  16. package/deploy/sema-up/lib/lanes.py +1 -1
  17. package/deploy/sema-up/lib/node-addrs.sh +42 -0
  18. package/deploy/sema-up/lib/parse-machines.py +2 -2
  19. package/deploy/sema-up/lib/shell-access.sh +1 -1
  20. package/deploy/sema-up/preflight.sh +4 -4
  21. package/deploy/sema-up/sema-up.sh +33 -33
  22. package/deploy/sema-up/smoke.sh +3 -3
  23. package/deploy/sema-up/stack/compose.yaml +1 -1
  24. package/deploy/sema-up/stack/sema-stack-cluster.yaml +26 -3
  25. package/dist/approval-card.d.ts +20 -4
  26. package/dist/approval-content-kind.d.ts +38 -22
  27. package/dist/approval-content-kind.js +20 -4
  28. package/dist/audit.js +3 -0
  29. package/dist/bench/s1/arms.d.ts +9 -37
  30. package/dist/bench/s1/arms.js +4 -61
  31. package/dist/bench/s1/live-deps.d.ts +4 -10
  32. package/dist/bench/s1/live-deps.js +1 -222
  33. package/dist/bench/s1/oracle.d.ts +1 -1
  34. package/dist/bench/s1/reviewer.d.ts +1 -1
  35. package/dist/bench/s1/row.d.ts +5 -7
  36. package/dist/bench/s1/row.js +0 -2
  37. package/dist/bench/s1/run-firm.d.ts +2 -2
  38. package/dist/bench/s1/run-firm.js +1 -4
  39. package/dist/bench/s1/runner-ctx.d.ts +17 -29
  40. package/dist/bench/s1/runner-ctx.js +3 -7
  41. package/dist/bench/s1/tasks.d.ts +9 -46
  42. package/dist/bench/s1/tasks.js +4 -63
  43. package/dist/boot/execution-env.d.ts +38 -26
  44. package/dist/boot/execution-env.js +87 -41
  45. package/dist/boot/leader.d.ts +2 -1
  46. package/dist/boot/memory-boundary.d.ts +1 -1
  47. package/dist/boot/memory-consolidation.d.ts +37 -3
  48. package/dist/boot/memory-consolidation.js +18 -2
  49. package/dist/boot/parked-revive-gate.d.ts +0 -3
  50. package/dist/boot/parked-revive-gate.js +2 -2
  51. package/dist/boot/resolve-spec.d.ts +0 -2
  52. package/dist/boot/resolve-spec.js +12 -17
  53. package/dist/boot/retention-lane.d.ts +12 -1
  54. package/dist/boot/retention-lane.js +2 -0
  55. package/dist/boot/runner-deps.d.ts +7 -6
  56. package/dist/boot/runner-deps.js +5 -16
  57. package/dist/boot/session-faces.d.ts +7 -2
  58. package/dist/boot/session-faces.js +37 -1
  59. package/dist/boot/stage-03-store-backend.d.ts +1 -0
  60. package/dist/boot/stage-03-store-backend.js +2 -2
  61. package/dist/boot/stage-04-stores.d.ts +1 -0
  62. package/dist/boot/stage-05-execution-env.d.ts +2 -2
  63. package/dist/boot/stage-05-execution-env.js +7 -4
  64. package/dist/boot/stage-06-runners.d.ts +2 -3
  65. package/dist/boot/stage-06-runners.js +13 -9
  66. package/dist/boot/stage-07-capability-layer.d.ts +2 -3
  67. package/dist/boot/stage-07-capability-layer.js +3 -4
  68. package/dist/boot/stage-08-reapers.d.ts +2 -3
  69. package/dist/boot/stage-08-reapers.js +2 -2
  70. package/dist/boot/stage-09-leader.d.ts +2 -3
  71. package/dist/boot/stage-09-leader.js +2 -1
  72. package/dist/boot/stage-10-http-server.d.ts +2 -3
  73. package/dist/boot/stage-10-http-server.js +2 -2
  74. package/dist/boot/stores.d.ts +1 -0
  75. package/dist/boot/stores.js +4 -3
  76. package/dist/boot/web-admin.d.ts +5 -0
  77. package/dist/boot/web-admin.js +28 -14
  78. package/dist/brain.d.ts +2 -2
  79. package/dist/brain.js +1 -1
  80. package/dist/capabilities/builtin-tools.d.ts +2 -1
  81. package/dist/capabilities/composite-members.d.ts +1 -1
  82. package/dist/capabilities/composite-members.js +1 -1
  83. package/dist/capabilities/hands-lane.d.ts +9 -6
  84. package/dist/capabilities/hands-lane.js +2 -2
  85. package/dist/capabilities/memory-notice.d.ts +27 -22
  86. package/dist/capabilities/memory-notice.js +15 -17
  87. package/dist/capabilities/scenarios.d.ts +9 -14
  88. package/dist/capabilities/scenarios.js +5 -50
  89. package/dist/capability-facts.d.ts +22 -11
  90. package/dist/capability-facts.js +13 -6
  91. package/dist/config-catalog.js +14 -5
  92. package/dist/config-provider.d.ts +5 -1
  93. package/dist/config-provider.js +23 -4
  94. package/dist/config-types.d.ts +19 -2
  95. package/dist/config.js +41 -6
  96. package/dist/deployment-governance.d.ts +19 -21
  97. package/dist/deployment-governance.js +7 -8
  98. package/dist/env-name-allowlist-knobs.d.ts +5 -5
  99. package/dist/env-name-allowlist-knobs.js +1 -0
  100. package/dist/execution-lane-caps.d.ts +12 -0
  101. package/dist/execution-lane-caps.js +18 -4
  102. package/dist/fleet/subagent-tail-bus.js +15 -5
  103. package/dist/hooks/hook-runner.d.ts +84 -30
  104. package/dist/hooks/hook-runner.js +74 -41
  105. package/dist/http/admission.js +17 -10
  106. package/dist/http/durable-run-leg.d.ts +5 -4
  107. package/dist/http/durable-run-leg.js +2 -4
  108. package/dist/http/idempotency.d.ts +28 -6
  109. package/dist/http/idempotency.js +10 -2
  110. package/dist/http/principal-gate.d.ts +14 -0
  111. package/dist/http/principal-gate.js +7 -0
  112. package/dist/http/request-guards.d.ts +2 -1
  113. package/dist/http/request-guards.js +14 -14
  114. package/dist/http/resume-legs.d.ts +2 -2
  115. package/dist/http/resume-legs.js +20 -10
  116. package/dist/http/route-ctx.d.ts +15 -7
  117. package/dist/http/routes/a2a-serve.js +11 -7
  118. package/dist/http/routes/approvals-assistant.js +18 -3
  119. package/dist/http/routes/background.d.ts +1 -1
  120. package/dist/http/routes/background.js +1 -1
  121. package/dist/http/routes/capabilities.js +10 -2
  122. package/dist/http/routes/mcp-reconnect.js +1 -1
  123. package/dist/http/routes/runs.d.ts +4 -3
  124. package/dist/http/routes/runs.js +35 -14
  125. package/dist/http/routes/session-sync.js +14 -11
  126. package/dist/http/routes/sessions.js +9 -9
  127. package/dist/http/routes/side-query.js +6 -19
  128. package/dist/http/routes/tasks.js +29 -19
  129. package/dist/http/routes/workflows.js +8 -0
  130. package/dist/http/server.d.ts +4 -0
  131. package/dist/http/server.js +3 -5
  132. package/dist/http/submit-replay.d.ts +15 -8
  133. package/dist/http/submit-replay.js +6 -0
  134. package/dist/http/wire-types.d.ts +7 -9
  135. package/dist/index.d.ts +1 -1
  136. package/dist/index.js +1 -1
  137. package/dist/internal-run-env.d.ts +30 -0
  138. package/dist/internal-run-env.js +11 -0
  139. package/dist/leader/wire.js +3 -2
  140. package/dist/lsp/manager.js +1 -1
  141. package/dist/memory-scope.d.ts +19 -7
  142. package/dist/memory-scope.js +25 -8
  143. package/dist/observability/fail-open.d.ts +31 -3
  144. package/dist/observability/fail-open.js +31 -3
  145. package/dist/observability/metrics.d.ts +0 -1
  146. package/dist/observability/metrics.js +1 -4
  147. package/dist/observability/run-terminal.js +72 -4
  148. package/dist/permission-rule-vocab.d.ts +3 -2
  149. package/dist/permission-rule-vocab.js +1 -1
  150. package/dist/plan-cache-probe.d.ts +3 -2
  151. package/dist/plugins/approval-ask-store-sql.d.ts +1 -1
  152. package/dist/plugins/caching-session-store.d.ts +42 -22
  153. package/dist/plugins/caching-session-store.js +19 -9
  154. package/dist/plugins/checkpoint-store-sql.d.ts +42 -28
  155. package/dist/plugins/checkpoint-store-sql.js +57 -11
  156. package/dist/plugins/file-run-store.d.ts +25 -21
  157. package/dist/plugins/file-run-store.js +70 -34
  158. package/dist/plugins/k8s-exec-protocol.js +3 -0
  159. package/dist/plugins/local-checkpoint-store.d.ts +8 -5
  160. package/dist/plugins/local-checkpoint-store.js +5 -15
  161. package/dist/plugins/local-session-store.d.ts +66 -7
  162. package/dist/plugins/local-session-store.js +168 -101
  163. package/dist/plugins/mailbox-recipient-lifecycle.d.ts +1 -1
  164. package/dist/plugins/memory-run-store.d.ts +19 -3
  165. package/dist/plugins/memory-run-store.js +38 -3
  166. package/dist/plugins/one-time-migrations.d.ts +165 -39
  167. package/dist/plugins/one-time-migrations.js +51 -144
  168. package/dist/plugins/pg-pool.js +11 -1
  169. package/dist/plugins/pg-session-storage.d.ts +2 -0
  170. package/dist/plugins/pg-session-storage.js +9 -5
  171. package/dist/plugins/remote-env-adb.d.ts +3 -0
  172. package/dist/plugins/remote-env-adb.js +1 -0
  173. package/dist/plugins/remote-env-device.d.ts +3 -0
  174. package/dist/plugins/remote-env-device.js +1 -0
  175. package/dist/plugins/remote-env-e2b.d.ts +4 -0
  176. package/dist/plugins/remote-env-e2b.js +2 -1
  177. package/dist/plugins/remote-env-host.d.ts +23 -1
  178. package/dist/plugins/remote-env-host.js +20 -2
  179. package/dist/plugins/remote-env-k8s.d.ts +264 -41
  180. package/dist/plugins/remote-env-k8s.js +551 -82
  181. package/dist/plugins/remote-env-local-docker.d.ts +4 -0
  182. package/dist/plugins/remote-env-local-docker.js +2 -1
  183. package/dist/plugins/remote-env-ssh.d.ts +3 -0
  184. package/dist/plugins/remote-env-ssh.js +1 -0
  185. package/dist/plugins/retention-store-sql.d.ts +4 -1
  186. package/dist/plugins/retention-store-sql.js +11 -9
  187. package/dist/plugins/run-store-sql.d.ts +44 -6
  188. package/dist/plugins/run-store-sql.js +92 -27
  189. package/dist/plugins/session-capture-record-store-sql.d.ts +2 -3
  190. package/dist/plugins/session-store.d.ts +4 -3
  191. package/dist/plugins/session-store.js +1 -1
  192. package/dist/plugins/sql-driver.d.ts +2 -1
  193. package/dist/plugins/store-backend.d.ts +12 -5
  194. package/dist/plugins/store-backend.js +13 -4
  195. package/dist/plugins/store-contracts.d.ts +20 -3
  196. package/dist/plugins/store-open-wait.js +3 -0
  197. package/dist/plugins/tidb-pool.js +15 -3
  198. package/dist/plugins/tidb-session-storage.js +3 -2
  199. package/dist/plugins/tidb-session-store.d.ts +2 -0
  200. package/dist/plugins/tidb-session-store.js +6 -2
  201. package/dist/request-key-closure.d.ts +32 -7
  202. package/dist/request-key-closure.js +25 -9
  203. package/dist/router/route-orchestration.d.ts +3 -11
  204. package/dist/router/route-orchestration.js +0 -4
  205. package/dist/rule-entry-list.js +0 -4
  206. package/dist/rules-consent.js +3 -0
  207. package/dist/run-acceptance.d.ts +51 -0
  208. package/dist/run-acceptance.js +27 -0
  209. package/dist/run-local.d.ts +5 -4
  210. package/dist/run-local.js +23 -17
  211. package/dist/runs.d.ts +7 -11
  212. package/dist/runs.js +6 -16
  213. package/dist/sandbox-egress-policy.d.ts +61 -0
  214. package/dist/sandbox-egress-policy.js +235 -0
  215. package/dist/security.d.ts +7 -0
  216. package/dist/security.js +5 -0
  217. package/dist/server-secret-env.d.ts +10 -4
  218. package/dist/server-secret-env.js +4 -1
  219. package/dist/session-error-wire.d.ts +2 -2
  220. package/dist/session-incarnation.d.ts +46 -2
  221. package/dist/session-incarnation.js +14 -3
  222. package/dist/session-sync-kernel.d.ts +10 -3
  223. package/dist/session-titler.d.ts +5 -3
  224. package/dist/spec-fields.d.ts +24 -8
  225. package/dist/spec-fields.js +21 -2
  226. package/dist/task-workflow.d.ts +6 -4
  227. package/dist/task-workflow.js +3 -2
  228. package/dist/tool-approval.d.ts +78 -6
  229. package/dist/tool-approval.js +7 -3
  230. package/dist/trace/core-keyset-guard.d.ts +6 -5
  231. package/dist/trace/engine-notice-wire.d.ts +26 -1
  232. package/dist/trace/engine-notice-wire.js +7 -2
  233. package/dist/trace/ledger-events.d.ts +9 -3
  234. package/dist/trace/ledger-sink.d.ts +7 -0
  235. package/dist/trace/ledger-sink.js +14 -4
  236. package/dist/trace/project.d.ts +57 -11
  237. package/dist/trace/project.js +54 -8
  238. package/dist/trace/self-minted-wire.d.ts +94 -2
  239. package/dist/trace/self-minted-wire.js +28 -0
  240. package/dist/trace/tool-output-media.d.ts +26 -0
  241. package/dist/trace/tool-output-media.js +57 -0
  242. package/dist/trace/wire-projection-faces.d.ts +7 -1
  243. package/dist/trace/wire-projection-faces.js +2 -1
  244. package/dist/web-admin-client/apply-effective.d.ts +13 -7
  245. package/dist/web-admin-client/apply-effective.js +11 -26
  246. package/dist/web-admin-client/apply-ledger.d.ts +2 -2
  247. package/dist/web-admin-client/candidate-gate.d.ts +39 -4
  248. package/dist/web-admin-client/candidate-gate.js +9 -2
  249. package/dist/web-admin-client/facade.d.ts +2 -2
  250. package/dist/web-admin-client/http-client.d.ts +3 -1
  251. package/dist/web-admin-client/http-client.js +4 -3
  252. package/dist/web-admin-client/read-warnings.d.ts +33 -5
  253. package/dist/web-admin-client/read-warnings.js +41 -6
  254. package/dist/web-admin-client/types.d.ts +11 -5
  255. package/dist/workspace-cache.d.ts +45 -0
  256. package/dist/workspace-cache.js +30 -0
  257. package/dist/workspace-space-commit.d.ts +116 -0
  258. package/dist/workspace-space-commit.js +117 -0
  259. package/dist/workspace-space.d.ts +75 -9
  260. package/dist/workspace-space.js +52 -1
  261. package/package.json +4 -4
  262. package/dist/boot/session-incarnation-seat.d.ts +0 -41
  263. package/dist/boot/session-incarnation-seat.js +0 -69
  264. package/dist/capabilities/code-review-council.d.ts +0 -49
  265. package/dist/capabilities/code-review-council.js +0 -111
  266. package/dist/capabilities/collab-wire.d.ts +0 -36
  267. package/dist/capabilities/collab-wire.js +0 -2
  268. package/dist/capabilities/collab-workflows.d.ts +0 -47
  269. package/dist/capabilities/collab-workflows.js +0 -90
  270. package/dist/capabilities/prompts/code-review.d.ts +0 -25
  271. package/dist/capabilities/prompts/code-review.js +0 -39
  272. package/dist/capabilities/prompts/team.d.ts +0 -10
  273. package/dist/capabilities/prompts/team.js +0 -6
  274. package/dist/capabilities/team.d.ts +0 -113
  275. package/dist/capabilities/team.js +0 -70
@@ -78,7 +78,7 @@ summary 会打印手动接法。
78
78
  | `--teardown` / `--teardown-volumes` | — | 卸载(留数据 / 连卷删) |
79
79
  | `--skip-preflight` | — | 跳过预检(不建议) |
80
80
 
81
- ### 取值旗的形(7.104.0,S-621)
81
+ ### 取值旗的形(7.104.0)
82
82
 
83
83
  一条规则:**每只取值旗都过形判**,不合 ⇒ 在建任何目录、写任何文件之前非零退出,拒句点名旗、收到的值、合法形。
84
84
  判据与闭集词表只在 `lib/flagshape.sh` 定义一次(sema-up / kube-up / cluster-up / preflight / smoke 同读;`--help` 的词表从它渲)。
@@ -0,0 +1,57 @@
1
+ {{- /*
2
+ 沙箱出网白名单(values: sandbox.networkPolicy)。沙箱 pod 由 server 的 k8s 车道按需创建、无固定标签,
3
+ 所以 podSelector 选整个 ns。只写 egress:沙箱不需要任何入站(server 经 k8s API exec 进去,不走网络)。
4
+ 放行:kube-dns 53;对象存储(chart 自带 MinIO 9000 + objectStore 点名的脸);IPv4 公网面(包源 / 代码托管)——
5
+ 私网 / 共享 / 链路本地 / 环回六段整段除外,公网面上的集群地址(clusterCidrs、nodeCidrs = 全部节点的 IPv4 地址)再除外。
6
+ IPv6 不写放行规则(NetworkPolicy 只有放行规则:写 ::/0 只会放宽,执行 v6 的集群上 v6 出网因此只剩上面点名的集群内脸;
7
+ 只执行 IPv4 的集群上 pod 的 v6 不受策略管,要关在 pod 侧 —— sandbox.ipv6)。
8
+ 这张策略是收窄,不是边界:pod 所在节点的往来流量是否放行由 CNI 的实现决定;宿主上 DNAT 的发布端口
9
+ (docker -p 一类)在策略评估之前改写目的地址,经任何节点地址都可能到达;CNI 不执行 NetworkPolicy 时整张不生效。
10
+ server 起服时读节点表与本策略,读出的缺口每个一行 sandbox_egress_policy_gap。
11
+ */ -}}
12
+ {{- if .Values.sandbox.networkPolicy.enabled }}
13
+ {{- $np := .Values.sandbox.networkPolicy }}
14
+ {{- if not $np.nodeCidrs }}{{ fail "sandbox.networkPolicy.nodeCidrs 必填(全部节点的 IPv4 地址,/32;kube-up 遍历节点自动填)" }}{{ end }}
15
+ {{- range $k, $list := dict "clusterCidrs" $np.clusterCidrs "nodeCidrs" $np.nodeCidrs }}
16
+ {{- range $list }}
17
+ {{- if or (not (contains "/" .)) (contains ":" .) }}{{ fail (printf "sandbox.networkPolicy.%s 的 %q 不是带前缀的 IPv4 CIDR(例 203.0.113.7/32;IPv6 没有放行规则,不用列)" $k .) }}{{ end }}
18
+ {{- end }}
19
+ {{- end }}
20
+ apiVersion: networking.k8s.io/v1
21
+ kind: NetworkPolicy
22
+ metadata:
23
+ name: sema-sandbox-egress
24
+ namespace: {{ .Values.sandbox.namespace }}
25
+ spec:
26
+ podSelector: {}
27
+ policyTypes: ["Egress"]
28
+ egress:
29
+ - to:
30
+ - namespaceSelector:
31
+ matchLabels: { kubernetes.io/metadata.name: kube-system }
32
+ podSelector:
33
+ matchLabels: { k8s-app: kube-dns }
34
+ ports:
35
+ - { protocol: UDP, port: 53 }
36
+ - { protocol: TCP, port: 53 }
37
+ - to:
38
+ - namespaceSelector:
39
+ matchLabels: { kubernetes.io/metadata.name: {{ .Release.Namespace }} }
40
+ podSelector:
41
+ matchLabels: { app: sema-minio }
42
+ ports:
43
+ - { protocol: TCP, port: 9000 }
44
+ {{- range $np.objectStore }}
45
+ - to:
46
+ - namespaceSelector:
47
+ matchLabels: { kubernetes.io/metadata.name: {{ .namespace | default $.Release.Namespace }} }
48
+ podSelector:
49
+ matchLabels: {{ toJson .podLabels }}
50
+ ports:
51
+ - { protocol: TCP, port: {{ .port }} }
52
+ {{- end }}
53
+ - to:
54
+ - ipBlock:
55
+ cidr: 0.0.0.0/0
56
+ except: {{ concat (list "10.0.0.0/8" "172.16.0.0/12" "192.168.0.0/16" "100.64.0.0/10" "169.254.0.0/16" "127.0.0.0/8") $np.clusterCidrs $np.nodeCidrs | uniq | toJson }}
57
+ {{- end }}
@@ -1,4 +1,4 @@
1
- # ── 沙箱 lane RBAC(k8s+kata;五动词)────────────────────────────────
1
+ # ── 沙箱 lane RBAC(k8s+kata;pod 五动词 + 缓存卷四动词 + 出网自检的两只只读:本 ns 的 NetworkPolicy、集群的节点表)────────────────────────────────
2
2
  apiVersion: v1
3
3
  kind: ServiceAccount
4
4
  metadata:
@@ -29,6 +29,14 @@ rules:
29
29
  - apiGroups: [""]
30
30
  resources: [pods/log]
31
31
  verbs: [get]
32
+ # 按工作区空间的构建缓存卷(WORKSPACE_CACHE=volume):连沙箱时按名读、没有就建;空间结束(会话删除 / 留存 sweep)按标签回收
33
+ - apiGroups: [""]
34
+ resources: [persistentvolumeclaims]
35
+ verbs: [get, create, delete, deletecollection]
36
+ # 起服的出网自检读本 ns 的 NetworkPolicy(只读)
37
+ - apiGroups: [networking.k8s.io]
38
+ resources: [networkpolicies]
39
+ verbs: [get, list]
32
40
  ---
33
41
  apiVersion: rbac.authorization.k8s.io/v1
34
42
  kind: RoleBinding
@@ -43,3 +51,26 @@ subjects:
43
51
  - kind: ServiceAccount
44
52
  name: sema-runner
45
53
  namespace: {{ .Values.sandbox.namespace }}
54
+ ---
55
+ # 出网自检读节点表(节点是集群级对象 ⇒ ClusterRole;只读两动词)。没给 ⇒ server 起服一行 sandbox_egress_policy_gap{kind: unreadable}。
56
+ apiVersion: rbac.authorization.k8s.io/v1
57
+ kind: ClusterRole
58
+ metadata:
59
+ name: sema-runner-nodes-{{ .Values.sandbox.namespace }}
60
+ rules:
61
+ - apiGroups: [""]
62
+ resources: [nodes]
63
+ verbs: [get, list]
64
+ ---
65
+ apiVersion: rbac.authorization.k8s.io/v1
66
+ kind: ClusterRoleBinding
67
+ metadata:
68
+ name: sema-runner-nodes-{{ .Values.sandbox.namespace }}
69
+ roleRef:
70
+ apiGroup: rbac.authorization.k8s.io
71
+ kind: ClusterRole
72
+ name: sema-runner-nodes-{{ .Values.sandbox.namespace }}
73
+ subjects:
74
+ - kind: ServiceAccount
75
+ name: sema-runner
76
+ namespace: {{ .Values.sandbox.namespace }}
@@ -56,11 +56,11 @@ spec:
56
56
  - { name: MODEL_ID, value: {{ required "serverV4pro.modelId is required" .Values.serverV4pro.modelId | quote }} }
57
57
  - { name: MODEL_API_KEY, valueFrom: { secretKeyRef: { name: sema-server-env, key: MODEL_API_KEY } } }
58
58
  - { name: MODEL_VISION, value: {{ .Values.server.modelVision | quote }} }
59
- {{/* S-600:租户姿态与主 worker 同值(文件头「同 env 面」的承诺;修前缺席 ⇒ 主 worker 多租时本只仍单用户)。 */}}
59
+ {{/* 租户姿态与主 worker 同值(文件头「同 env 面」的承诺;修前缺席 ⇒ 主 worker 多租时本只仍单用户)。 */}}
60
60
  - { name: REQUIRE_PRINCIPAL, value: {{ .Values.server.requirePrincipal | default "false" | quote }} }
61
61
  - { name: SANDBOX_PKG_SOURCE, value: {{ .Values.server.sandboxPkgSource | quote }} }
62
62
  - { name: REMOTE_EXEC, value: k8s }
63
- {{/* S-599:车道点名了就显式表态「这台有手」——REQUIRE_EXECUTION_LANE 让「车道被谁改没了」
63
+ {{/* 车道点名了就显式表态「这台有手」——REQUIRE_EXECUTION_LANE 让「车道被谁改没了」
64
64
  变成拒启而不是安静的无手 worker。server 侧默认仍 off,sema-up 产物一律写 true。 */}}
65
65
  - { name: REQUIRE_EXECUTION_LANE, value: "true" }
66
66
  - { name: K8S_API_URL, value: "https://kubernetes.default.svc" }
@@ -70,6 +70,7 @@ spec:
70
70
  - { name: K8S_NAMESPACE, value: {{ .Values.sandbox.namespace }} }
71
71
  - { name: K8S_RUNTIME_CLASS, value: {{ .Values.sandbox.runtimeClass }} }
72
72
  - { name: K8S_SANDBOX_IMAGE, value: {{ .Values.sandbox.image | quote }} }
73
+ - { name: K8S_SANDBOX_IPV6, value: {{ .Values.sandbox.ipv6 | quote }} }
73
74
  - { name: K8S_TOKEN, valueFrom: { secretKeyRef: { name: sema-runner-token-copy, key: token } } }
74
75
  readinessProbe: # the only probe path is /readyz (/health is diagnostic, always 200)
75
76
  httpGet: { path: /readyz, port: 8090 }
@@ -71,7 +71,7 @@ spec:
71
71
  - { name: REQUIRE_PRINCIPAL, value: {{ .Values.server.requirePrincipal | default "false" | quote }} }
72
72
  - { name: SANDBOX_PKG_SOURCE, value: {{ .Values.server.sandboxPkgSource | quote }} }
73
73
  - { name: REMOTE_EXEC, value: k8s }
74
- {{/* S-599:车道点名了就显式表态「这台有手」——REQUIRE_EXECUTION_LANE 让「车道被谁改没了」
74
+ {{/* 车道点名了就显式表态「这台有手」——REQUIRE_EXECUTION_LANE 让「车道被谁改没了」
75
75
  变成拒启而不是安静的无手 worker。server 侧默认仍 off,sema-up 产物一律写 true。 */}}
76
76
  - { name: REQUIRE_EXECUTION_LANE, value: "true" }
77
77
  - { name: K8S_API_URL, value: "https://kubernetes.default.svc" }
@@ -83,6 +83,7 @@ spec:
83
83
  - { name: K8S_RUNTIME_CLASS, value: {{ .Values.sandbox.runtimeClass }} }
84
84
  {{- end }}
85
85
  - { name: K8S_SANDBOX_IMAGE, value: {{ .Values.sandbox.image | quote }} }
86
+ - { name: K8S_SANDBOX_IPV6, value: {{ .Values.sandbox.ipv6 | quote }} }
86
87
  - { name: K8S_TOKEN, valueFrom: { secretKeyRef: { name: sema-runner-token-copy, key: token } } }
87
88
  readinessProbe: # the only probe path is /readyz (/health is diagnostic, always 200)
88
89
  httpGet: { path: /readyz, port: 8090 }
@@ -110,6 +110,28 @@ sandbox:
110
110
  # 小巧默认,重任务用 sandboxImageProfile 按需选 code-python/code-full 等,Hub 池 public 匿名可拉)。
111
111
  # 裸 OS 镜像(如 ubuntu)没有 pkg-source hook——sandboxPkgSource=global 时官方源不会材料化,别退回。
112
112
  image: docker.io/claybobby/code-node:20260707-749ab84f5fdd-786f5ef10ffd
113
+ # 沙箱 pod 的 IPv6(→ server env K8S_SANDBOX_IPV6;词:enabled | disabled —— 不写 on/off,YAML 会读成布尔):
114
+ # disabled = pod 级 sysctl 关 IPv6(net.ipv6.conf.all / default.disable_ipv6=1)。两只都不在 k8s 的 safe sysctl 表里 ⇒
115
+ # 每个节点的 kubelet 要 --allowed-unsafe-sysctls 点名它们,否则沙箱 pod 起不来;沙箱 ns 不能 enforce PodSecurity baseline。
116
+ # enabled = 不动 pod(缺省):只执行 IPv4 的出网策略(k3s 单栈缺省即是)管不到 pod 的 IPv6,server 起服每次一行提醒。
117
+ ipv6: enabled
118
+ # 沙箱出网策略(NetworkPolicy,egress 白名单;要集群 CNI 带 NetworkPolicy 控制器 —— k3s 缺省自带):
119
+ # 放行 = DNS(kube-dns)+ 对象存储(chart 自带的 MinIO 9000,加 objectStore 点名的脸)+ IPv4 公网面;
120
+ # 拒 = 私网 / 共享 / 链路本地 / 环回六段(10/8、172.16/12、192.168/16、100.64/10、169.254/16、127/8)整段,
121
+ # 加公网面上的集群地址:clusterCidrs(pod / service 段,k3s 缺省值;别的发行版按实填)与 nodeCidrs;IPv6 不写地址块放行(只剩上面点名的集群内脸)。
122
+ # nodeCidrs = 全部节点的全部 IPv4 Internal / External 地址(/32;kube-up 遍历节点自动填),enabled 时必填;两张表只收带前缀的
123
+ # IPv4 CIDR。手写 values 的部署按实列,新加节点要补(server 起服会把落在放行面里的节点地址逐个报 sandbox_egress_policy_gap)。
124
+ # 射程:这是收窄、不是边界 —— pod 所在节点的往来流量是否放行由 CNI 实现决定;宿主上 DNAT 的发布端口(docker -p 一类)在策略
125
+ # 评估之前改写目的地址,经任何节点地址都可能到达;要访问私网里的包源 / 代码托管,在沙箱 ns 另建一条 NetworkPolicy 放行那个
126
+ # 地址(策略按并集叠加)。
127
+ # objectStore = 集群内还要放行的对象存储脸(pod 标签 + 端口;namespace 省略 = 跟本 release 的 ns):s3PublicEndpoint 指向
128
+ # NodePort 时,沙箱打到节点 IP 的流量被 kube-proxy DNAT 到背后的反代 pod,策略看到的是那个 pod —— 所以要按 pod 点名。
129
+ networkPolicy:
130
+ enabled: true
131
+ clusterCidrs: ["10.42.0.0/16", "10.43.0.0/16"]
132
+ nodeCidrs: []
133
+ objectStore:
134
+ - { podLabels: { app: sema-ip-proxy }, port: 8445 }
113
135
 
114
136
  # 私有 registry 拉取(6b:secret 由 cluster-up 建 + patch default SA;这里的显式引用是纵深,
115
137
  # 留空=只靠 SA 注入)
@@ -7,7 +7,7 @@
7
7
  #
8
8
  # 输入(sema-up.sh 解析 machines.yaml 后注入):
9
9
  # MACHINE_COUNT + MACHINE_<i>_{HOST,USER,SSH_KEY,NAME,ROLE,PRIVATE_IP,PUBLIC_IFACE}
10
- # WORK(状态目录,.env 在此)REGION PROJECT USERS(single|multi,缺省 single;S-600:翻成主 worker 的 REQUIRE_PRINCIPAL)
10
+ # WORK(状态目录,.env 在此)REGION PROJECT USERS(single|multi,缺省 single;翻成主 worker 的 REQUIRE_PRINCIPAL)
11
11
  # SEMA_SERVER_IMAGE(registry 引用)或 SEMA_SERVER_IMAGE_TAR(本地 docker save tar[.gz])二选一
12
12
  # MODEL_GATEWAY_BASEURL MODEL_ID MODEL_API_KEY
13
13
  # ALLOW_SMALL_CLUSTER=true 放行 <3 机(dev/CI 单节点验流程;生产必须 >=3 奇数)
@@ -25,11 +25,11 @@ done
25
25
  HERE="$(cd "$(dirname "$_self")" && pwd)"
26
26
  unset _self _hops _dir
27
27
  # <<< 自身目录
28
- # `.env` 的文法与全部读写原语只在 lib/envf.sh 定义(S-618 续):本脚本不再有自己的 setk / `. "$ENVF"`。
28
+ # `.env` 的文法与全部读写原语只在 lib/envf.sh 定义:本脚本不再有自己的 setk / `. "$ENVF"`。
29
29
  . "$HERE/lib/envf.sh"
30
- # 「壳怎么接这台引擎」的渲染(S-850;sema-up.sh / kube-up.sh 同一只)。
30
+ # 「壳怎么接这台引擎」的渲染(sema-up.sh / kube-up.sh 同一只)。
31
31
  . "$HERE/lib/shell-access.sh"
32
- # 取值旗的形(S-621):判据与词表同 sema-up.sh 一处定义。
32
+ # 取值旗的形:判据与词表同 sema-up.sh 一处定义。
33
33
  . "$HERE/lib/flagshape.sh"
34
34
  # 引擎 /health 体里「落在哪个后端」的读法与期望值(smoke.sh / kube-up.sh 同一只)。
35
35
  . "$HERE/lib/health.sh"
@@ -46,15 +46,15 @@ CNPG_VERSION="${CNPG_VERSION:-1.30.0}" # ⚠ in-tree barman 1.31 移除;升版
46
46
  LONGHORN_VERSION="${LONGHORN_VERSION:-1.10.0}"
47
47
  KATA_VERSION="${KATA_VERSION:-3.21.0}"
48
48
  STACK_ENGINE="${STACK_ENGINE:-render}" # sema-stack 装配引擎:render(as-built 渲染 apply,缺省)| helm
49
- USERS_GIVEN="${USERS:+1}" # S-600:显式给没给(缺省之前记下;决策见下方 users_decide)
50
- USERS="${USERS:-single}" # 租户形(S-600):经 principal_of_users 翻成 REQUIRE_PRINCIPAL,两条装配路径同一次翻译
49
+ USERS_GIVEN="${USERS:+1}" # 显式给没给(缺省之前记下;决策见下方 users_decide)
50
+ USERS="${USERS:-single}" # 租户形:经 principal_of_users 翻成 REQUIRE_PRINCIPAL,两条装配路径同一次翻译
51
51
  NODEPORT=30890
52
52
 
53
- # 取值旗的形(S-621)——在对任何一台机器发起 ssh 之前。修前:REGION=eu 当成「非 cn 非 global」、STACK_ENGINE=x 当成 render。
53
+ # 取值旗的形——在对任何一台机器发起 ssh 之前。修前:REGION=eu 当成「非 cn 非 global」、STACK_ENGINE=x 当成 render。
54
54
  flag_enum "--region(REGION)" "$REGION" $FLAG_WORDS_REGION
55
55
  flag_enum "STACK_ENGINE" "$STACK_ENGINE" $FLAG_WORDS_STACK_ENGINE
56
56
  flag_enum "--users(USERS)" "$USERS" $FLAG_WORDS_USERS
57
- # S-600:租户形 = 显式 USERS ∨ 上一次落下的部署事实 ∨ single(lib/flagshape.sh 的 users_decide)——在任何 ssh 之前判,
57
+ # 租户形 = 显式 USERS ∨ 上一次落下的部署事实 ∨ single(lib/flagshape.sh 的 users_decide)——在任何 ssh 之前判,
58
58
  # 不带旗的重跑不会把多租部署降成单用户。
59
59
  ENVF="$WORK/.env"
60
60
  users_decide "$USERS_GIVEN"
@@ -339,10 +339,10 @@ for k in MINIO_PASSWORD SERVICE_AUTH_TOKEN; do
339
339
  _v="$(envf_get "$k")" || exit 1
340
340
  [ "${#_v}" -ge 32 ] || die "$k 生成失败(openssl rand?)——检查 $ENVF"
341
341
  done
342
- # A(S-618 续):`.env` 不 source —— 只回读本脚本自己落盘的两只凭据;输入键(MODEL_API_KEY / 网关 / 镜像……)
342
+ # `.env` 不 source —— 只回读本脚本自己落盘的两只凭据;输入键(MODEL_API_KEY / 网关 / 镜像……)
343
343
  # 以本次传入的环境为准,不再被 .env 旧值覆盖。
344
344
  envf_load MINIO_PASSWORD SERVICE_AUTH_TOKEN
345
- resetk REQUIRE_PRINCIPAL "$(principal_of_users "$USERS")" # S-600:部署事实(下次不带旗重跑据此沿用租户形)
345
+ resetk REQUIRE_PRINCIPAL "$(principal_of_users "$USERS")" # 部署事实(下次不带旗重跑据此沿用租户形)
346
346
  [ -n "${MODEL_API_KEY:-}" ] || die "需要 MODEL_API_KEY(-f 配置或 --model-key)"
347
347
  # PG 实例数/反亲和/副本数按机器数缩放(<3 机=dev:preferred,required 会永久 Pending)
348
348
  PG_INSTANCES=$(( MACHINE_COUNT >= 3 ? 3 : MACHINE_COUNT ))
@@ -27,16 +27,18 @@ HERE="$(cd "$(dirname "$_self")" && pwd)"
27
27
  unset _self _hops _dir
28
28
  # <<< 自身目录
29
29
  # `.env` 的文法与全部读写原语(envf_get / envf_has / envf_load / envf_put / setk / setk_new / resetk)只在这一处
30
- # 定义,sema-up.sh / cluster-up.sh / smoke.sh 同源(S-618 续):本脚本不再有自己的 setk / has_env / `. "$ENVF"`。
30
+ # 定义,sema-up.sh / cluster-up.sh / smoke.sh 同源:本脚本不再有自己的 setk / has_env / `. "$ENVF"`。
31
31
  . "$HERE/lib/envf.sh"
32
- # 「壳怎么接这台引擎」的渲染(S-850;sema-up.sh / cluster-up.sh 同一只)。
32
+ # 「壳怎么接这台引擎」的渲染(sema-up.sh / cluster-up.sh 同一只)。
33
33
  . "$HERE/lib/shell-access.sh"
34
- # 取值旗的形(S-621):判据与词表同 sema-up.sh 一处定义。
34
+ # 取值旗的形:判据与词表同 sema-up.sh 一处定义。
35
35
  . "$HERE/lib/flagshape.sh"
36
36
  # 引擎 /health 体里「落在哪个后端」的读法与期望值(smoke.sh / cluster-up.sh 同一只)。
37
37
  . "$HERE/lib/health.sh"
38
38
  # 对象存储桶的唯一表(sema-up.sh / cluster-up.sh / smoke.sh 同读这一张)。
39
39
  . "$HERE/lib/buckets.sh"
40
+ # 集群节点地址的唯一读法(NodePort 入口 + 沙箱出网策略要拒的全部节点地址;同读一份节点表)。
41
+ . "$HERE/lib/node-addrs.sh"
40
42
  log() { printf '[kube-up] %s\n' "$*" >&2; }
41
43
  die() { log "⛔ $*"; exit 1; }
42
44
 
@@ -45,7 +47,7 @@ PROJECT="${PROJECT:-sema}"
45
47
  REGION="${REGION:-global}"
46
48
  KUBE_MODE="${KUBE_MODE:?KUBE_MODE 未设置(existing|k3s)}"
47
49
  DRY_RUN="${DRY_RUN:-false}"
48
- USERS_GIVEN="${USERS:+1}" # S-600:显式给没给(缺省 single 之前记下;决策见下方 users_decide)
50
+ USERS_GIVEN="${USERS:+1}" # 显式给没给(缺省 single 之前记下;决策见下方 users_decide)
49
51
  USERS="${USERS:-single}"
50
52
  REGISTRY_ENABLED="${REGISTRY_ENABLED:-true}"
51
53
  GIT_MODE="${GIT_MODE:-none}"
@@ -53,7 +55,7 @@ NAMESPACE="${NAMESPACE:-sema}"
53
55
  CNPG_VERSION="${CNPG_VERSION:-1.30.0}" # ⚠ in-tree barman 1.31 移除;升版前先迁 barman-cloud plugin
54
56
  K3S_CHANNEL="${K3S_CHANNEL:-stable}"
55
57
 
56
- # ── 取值旗的形(S-621)——在装 k3s / 动集群 / 建 WORK 之前 ─────────────────────────────────────────
58
+ # ── 取值旗的形——在装 k3s / 动集群 / 建 WORK 之前 ─────────────────────────────────────────
57
59
  # 单独跑时这些环境变量就是本脚本的旗;经 sema-up 进来的值那边已判过,这里同一只再判一次(本脚本自己也是入口)。
58
60
  # 修前:DRY_RUN=1 ≠ true ⇒ 当成真装;REGISTRY_ENABLED=yes 当关;USERS=team 当 single;KUBE_MODE=foo 走 existing 那一臂。
59
61
  flag_enum "--kube(KUBE_MODE)" "$KUBE_MODE" $FLAG_WORDS_KUBE_SINGLE # machines 走 cluster-up.sh,不进本脚本
@@ -62,7 +64,7 @@ flag_enum "--users(USERS)" "$USERS" $FLAG_WORDS_USERS
62
64
  flag_bool "--registry(REGISTRY_ENABLED)" "$REGISTRY_ENABLED"
63
65
  flag_enum "--git(GIT_MODE)" "$GIT_MODE" $FLAG_WORDS_GIT
64
66
  flag_enum "--region(REGION)" "$REGION" $FLAG_WORDS_REGION
65
- # S-600:租户形 = 显式 USERS ∨ 上一次落下的部署事实 ∨ single(规则与拒句在 lib/flagshape.sh 的 users_decide)——
67
+ # 租户形 = 显式 USERS ∨ 上一次落下的部署事实 ∨ single(规则与拒句在 lib/flagshape.sh 的 users_decide)——
66
68
  # 在动集群之前判,不带旗的重跑不会把多租部署降成单用户。
67
69
  ENVF="$WORK/.env"
68
70
  users_decide "$USERS_GIVEN"
@@ -178,7 +180,7 @@ mkdir -p "$WORK"; chmod 700 "$WORK" 2>/dev/null || true
178
180
  touch "$ENVF"; chmod 600 "$ENVF"
179
181
  setk MINIO_PASSWORD "$(openssl rand -hex 24)"
180
182
  setk SERVICE_AUTH_TOKEN "$(openssl rand -hex 24)"
181
- resetk REQUIRE_PRINCIPAL "$(principal_of_users "$USERS")" # S-600:部署事实(下次不带旗重跑据此沿用租户形)
183
+ resetk REQUIRE_PRINCIPAL "$(principal_of_users "$USERS")" # 部署事实(下次不带旗重跑据此沿用租户形)
182
184
  NEW_REG_PW=false NEW_GIT_PW=false
183
185
  if [ "$REGISTRY_ENABLED" = "true" ]; then
184
186
  setk_new REGISTRY_ADMIN_PASSWORD "$(openssl rand -hex 24)" && NEW_REG_PW=true
@@ -194,15 +196,19 @@ for k in MINIO_PASSWORD SERVICE_AUTH_TOKEN; do
194
196
  _v="$(envf_get "$k")" || exit 1
195
197
  [ "${#_v}" -ge 32 ] || die "$k 生成失败(openssl rand?)——检查 $ENVF"
196
198
  done
197
- # A(S-618 续):`.env` 不 source —— 只回读**本脚本自己落盘**的键(凭据 / 已登记的 OAuth 接线)到同名 shell 变量。
199
+ # `.env` 不 source —— 只回读**本脚本自己落盘**的键(凭据 / 已登记的 OAuth 接线)到同名 shell 变量。
198
200
  # 输入键(镜像 / 网关 / 模型 id / MODEL_API_KEY / GIT_URL / GIT_TOKEN)以本次传入的环境为准,不再被 .env 旧值覆盖
199
201
  # (旧 source 会拿上一次的 GIT_TOKEN 盖掉这次传进来的新 token —— sema-up.sh connect 段早就踩过、改成了 resetk)。
200
202
  envf_load MINIO_PASSWORD SERVICE_AUTH_TOKEN REGISTRY_ADMIN_PASSWORD REGISTRY_SESSION_SECRET REGISTRY_PULL_TOKEN \
201
203
  GIT_ADMIN_USER GIT_ADMIN_PASSWORD REGISTRY_GITEA_BASE_URL REGISTRY_GITEA_OAUTH_ID REGISTRY_GITEA_OAUTH_SECRET
202
204
  [ -n "${MODEL_API_KEY:-}" ] || die "需要 MODEL_API_KEY(--model-key 或 -f 配置)"
203
205
 
204
- # 节点 IP(NodePort 入口;kind 场景宿主上不可达,summary 会给 port-forward 替代)
205
- NODE_IP=$($KUBECTL get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}' | awk '{print $1}')
206
+ # 节点表读一次,两个读数(lib/node-addrs.sh):
207
+ # · NODE_IP = 第一只节点的第一只 InternalIP —— NodePort 入口(kind 场景宿主上不可达,summary 会给 port-forward 替代);
208
+ # · NODE_CIDRS = 全部节点的全部 IPv4 Internal / External 地址(/32)—— 沙箱出网策略的 nodeCidrs(不止 items[0]、不止第一只地址)。
209
+ NODES_JSON="$($KUBECTL get nodes -o json)" || die "读不到节点表(kubectl get nodes)。下一步:核 kubeconfig 与权限"
210
+ NODE_IP="$(node_primary_ip "$NODES_JSON")" || die "节点表里第一只节点没有 InternalIP —— NodePort 入口定不下来。下一步:kubectl get nodes -o wide"
211
+ NODE_CIDRS="$(node_cidrs_json "$NODES_JSON")" || die "节点表里读不出任何 IPv4 节点地址 —— 沙箱出网策略要拒的节点地址列不出来,不装一份漏了节点的策略。下一步:kubectl get nodes -o wide"
206
212
 
207
213
  # ── 5. helm 装配(凭据经 stdin;两遍:git=provision 时先无 OAuth 起栈,引导完 Gitea
208
214
  # 再带 OAuth 升级——registry 第一遍已可表单登录,不是半成品)────────────────────
@@ -217,7 +223,7 @@ helm_values() { # helm_values <giteaBaseUrl> <oauthId> <oauthSecret>
217
223
  V_REG_ENABLED="$REGISTRY_ENABLED" V_REG_IMAGE="${SEMA_REGISTRY_IMAGE:-}" \
218
224
  V_REG_PW="${REGISTRY_ADMIN_PASSWORD:-}" V_REG_SS="${REGISTRY_SESSION_SECRET:-}" V_REG_PT="${REGISTRY_PULL_TOKEN:-}" \
219
225
  V_GITEA_ENABLED="$([ "$GIT_MODE" = provision ] && echo true || echo false)" \
220
- V_GITEA_IMAGE="${GITEA_IMAGE:-gitea/gitea:1.24}" V_NODE_IP="$NODE_IP" \
226
+ V_GITEA_IMAGE="${GITEA_IMAGE:-gitea/gitea:1.24}" V_NODE_IP="$NODE_IP" V_NODE_CIDRS="$NODE_CIDRS" \
221
227
  V_MINIO_IMAGE="${MINIO_IMAGE:-}" \
222
228
  python3 - <<'PY'
223
229
  import json, os
@@ -240,7 +246,8 @@ v = {
240
246
  "modelId": e["V_MODEL_ID"], "modelApiKey": e["V_MODEL_KEY"],
241
247
  "sandboxPkgSource": e["V_PKG_SOURCE"], "requirePrincipal": e["V_REQ_PRINCIPAL"],
242
248
  },
243
- "sandbox": {"runtimeClass": e["V_RT_CLASS"]},
249
+ "sandbox": {"runtimeClass": e["V_RT_CLASS"],
250
+ "networkPolicy": {"nodeCidrs": json.loads(e["V_NODE_CIDRS"])}},
244
251
  "registry": {"enabled": e["V_REG_ENABLED"] == "true", "image": e["V_REG_IMAGE"],
245
252
  "storageClass": e["V_SC"], "adminPassword": e["V_REG_PW"],
246
253
  "sessionSecret": e["V_REG_SS"], "pullToken": e["V_REG_PT"],
@@ -360,7 +367,7 @@ except Exception: print("")')
360
367
  [ -n "$GTOK" ] || die "Gitea access token 生成失败。下一步:kubectl -n $NAMESPACE logs deploy/sema-gitea"
361
368
  setk GIT_ADMIN_TOKEN "$GTOK"
362
369
  fi
363
- envf_load GIT_ADMIN_TOKEN # A:回读刚生成 / 已存的 token,不 source .env
370
+ envf_load GIT_ADMIN_TOKEN # 回读刚生成 / 已存的 token,不 source .env
364
371
  if [ "$REGISTRY_ENABLED" = "true" ] && ! envf_has REGISTRY_GITEA_OAUTH_ID; then
365
372
  REDIRECT="http://$NODE_IP:30300/api/auth/oauth/callback"
366
373
  RESP=$($KUBECTL exec deploy/sema-gitea -n "$NAMESPACE" -- \
@@ -1,4 +1,4 @@
1
- # lib/dataroot.sh — 数据根归属的唯一规则(S-851,7.104.0)。sema-up.sh(判定 / 落定 / 卸载提示)与 preflight.sh(多盘机
1
+ # lib/dataroot.sh — 数据根归属的唯一规则(7.104.0)。sema-up.sh(判定 / 落定 / 卸载提示)与 preflight.sh(多盘机
2
2
  # 建议句)都从这里取,不各写一份。
3
3
  #
4
4
  # 规则:一条数据根归**一个**项目所有 ——
@@ -1,17 +1,17 @@
1
1
  # shellcheck shell=bash
2
2
  # lib/envf.sh — sema-up 家族 `.env` 的文法**与全部读写原语**,定义在这一处。
3
3
  #
4
- # 立场(S-618,一次收完 test 实测(srv796)报的一类):`.env` 是**数据**,永不 `source`。值里的
4
+ # 立场(一次收完 test 实测(srv796)报的一类):`.env` 是**数据**,永不 `source`。值里的
5
5
  # `$(...)` / 反引号 / `;` / 空白在这里是字符串,不是代码;读值一律经数据解析(envf_get / envf_has /
6
6
  # envf_load),写值一律经 envf_put(setk / setk_new / resetk 都落到它),绝不把 `.env` 交给 shell 执行。
7
7
  #
8
8
  # 使用者 = deploy/sema-up 下所有碰 `.env` 的脚本(sema-up.sh / kube-up.sh / cluster-up.sh / smoke.sh):
9
9
  # 各自 `. "$HERE/lib/envf.sh"`,调用前设好 `ENVF`(`.env` 路径)。脚本里**不许**再有自己的 setk /
10
10
  # has_env / `. "$ENVF"` / `printf '%s=%s' >> "$ENVF"` / `grep … "$ENVF"` —— 第二套写读规则迟早分叉
11
- # (test/deploy-lanes-contract.test.ts「S-618 续」两道机器钉)。
11
+ # (test/deploy-lanes-contract.test.ts 里「写口唯一」格与 smoke / kube-up / cluster-up 收进同一文法那一组,共两道机器钉)。
12
12
  #
13
- # **一条文法,两半共用。** 文法的依据是 compose-go dotenv 的**真实**读法(车MV / S-646,k3s8 docker compose 2.40.3
14
- # 逐形实跑的语料,金样钉在 test/deploy-lanes-contract.test.ts「S-656 + S-646」):一行 `KEY=<右半>` 的右半有三种形,
13
+ # **一条文法,两半共用。** 文法的依据是 compose-go dotenv 的**真实**读法(车MV,k3s8 docker compose 2.40.3
14
+ # 逐形实跑的语料,金样钉在 test/deploy-lanes-contract.test.ts 里「.env 文法与渲染对账对齐 compose 真实语义」那一组):一行 `KEY=<右半>` 的右半有三种形,
15
15
  # 每种形里只有少数几个字符会让 compose **改写**读到的值 —— 不碰这几个字符,compose 读到的就是字面量:
16
16
  # · 裸值 `KEY=v`:插值起点(`$` 后跟 `$` / `{` / 字母或 `_`,见 envf_has_interp)、「空格 + `#`」(行内注释;只认 ASCII 空格,`\t#` 是字面)、首尾空白(修剪 —— 开头按
17
17
  # compose-go 自己的 isSpace = ASCII 空白 + U+0085 + U+00A0,结尾按 Go `unicode.IsSpace`,多出全角空格等 16 个)、
@@ -35,7 +35,7 @@
35
35
  # 裸写则 bash 语法错)、以奇数个 `\` 结尾(单引号形 compose 闭引号失效;裸写则 bash 当续行吞下一行)⇒ **写之前**响亮拒,
36
36
  # 点名键、不回显值,「下一步」按拒因给。写口产物恒在读口文法内(安全裸词 ⊂ 裸值形,单引号编码形 ⊂ 单引号形)⇒ 往返成立。
37
37
  #
38
- # 收编(S-618):7.96.0「写口只拒换行 / 回车」的判据、`envf_get` 的物理行假设,连同曾经的「另立
38
+ # 收编:7.96.0「写口只拒换行 / 回车」的判据、`envf_get` 的物理行假设,连同曾经的「另立
39
39
  # 一件做渲染对账」都收进来——写口判据 = 本文件的 `envf_representable`;物理行假设的兜底 = 生成 `.env`
40
40
  # 之后、`compose up` 之前那一道 `docker compose config` 渲染对账(sema-up.sh `reconcile_render`,
41
41
  # 以 compose 自己为唯一属主)。不再有第二套文法。
@@ -1,4 +1,4 @@
1
- # lib/flagshape.sh — 取值旗的形(S-621,7.104.0):一条规则、一处定义(判据 + 词表)。sema-up.sh(参数解析之后、建任何目录之前)、
1
+ # lib/flagshape.sh — 取值旗的形(7.104.0):一条规则、一处定义(判据 + 词表)。sema-up.sh(参数解析之后、建任何目录之前)、
2
2
  # kube-up.sh / cluster-up.sh(单独跑时环境变量就是它们的旗)、preflight.sh / smoke.sh 都从这里判,不各写一份。
3
3
  #
4
4
  # 规则:每只取值旗都过形判;不合 ⇒ 拒句点名旗、收到的值、合法形,非零退出 —— 调用方把判放在任何建目录 / 写文件 / 动集群 /
@@ -7,7 +7,7 @@
7
7
  # · port —— 1–65535 的十进制整数,不带前导 0 / 正负号 / 空白(前导 0 在 bash 算术里读成八进制);
8
8
  # · enum —— 列全词(词表就在下面:--help、拒句、交互选项的对拍钉都从这里取,不手抄);
9
9
  # · project —— compose 项目名形(小写字母 / 数字 / - / _,首字符字母或数字):它也是工作目录 ~/.sema-up/<名> 与自动数据根
10
- # <盘>/sema-data/<名> 的一段路径(S-851)—— `..` / `/` / 空串会把两者指到别处。
10
+ # <盘>/sema-data/<名> 的一段路径—— `..` / `/` / 空串会把两者指到别处。
11
11
  # 自由文本(URL / 镜像引用 / 路径 / 主机名 / 模型 id / 凭据)不在这里判:合法形不是闭集,各有自己的消费点(落 .env 的值
12
12
  # 另过 lib/envf.sh 的写口)。盘点见 deploy/sema-up/README.md「取值旗的形」。
13
13
  #
@@ -18,8 +18,8 @@
18
18
  # ── 词表(单一属主)──────────────────────────────────────────────────────────────────────────────
19
19
  FLAG_WORDS_PROFILE="full-single data-center local-plus full-cluster"
20
20
  FLAG_WORDS_USERS="single multi"
21
- # 租户形 ⇒ 容器上 REQUIRE_PRINCIPAL 的值 —— 这条翻译的**唯一**定义(S-600,7.105.0 从 sema-up.sh 搬来):sema-up 的 compose 生成段 /
22
- # 事实核对,kube-up 的 helm values,cluster-up 的渲染清单与 helm values 同调这一只(修前 kube-up 另写一份同义翻译,S-619 D5;
21
+ # 租户形 ⇒ 容器上 REQUIRE_PRINCIPAL 的值 —— 这条翻译的**唯一**定义(7.105.0 从 sema-up.sh 搬来):sema-up 的 compose 生成段 /
22
+ # 事实核对,kube-up 的 helm values,cluster-up 的渲染清单与 helm values 同调这一只(修前 kube-up 另写一份同义翻译;
23
23
  # cluster-up 一份都没有 ⇒ --users=multi 在 --kube=machines 路径上被静默丢成单用户)。只认两词,别的词先过 flag_enum。
24
24
  principal_of_users() { [ "$1" = "multi" ] && echo true || echo false; }
25
25
 
@@ -27,7 +27,7 @@ principal_of_users() { [ "$1" = "multi" ] && echo true || echo false; }
27
27
  # compose 档同一条规则:**决策 = 显式 USERS ∨ 上一次落在 $ENVF 的部署事实 REQUIRE_PRINCIPAL ∨ single**;显式值与事实
28
28
  # 不一致 ⇒ 拒并点名两处(不静默把一台多租部署降成单用户,也不静默把单用户升成多租)。事实 → 租户词只经
29
29
  # principal_of_users 反查(两词逐个过正向比,不另写反表);认不出的事实值 ⇒ 拒。设 USERS。
30
- # S-600 codex 一轮 [high]:machines 路径开始认 --users 之后,一次不带旗的重跑会拿缺省 single 把多租部署的
30
+ # codex 一轮 [high]:machines 路径开始认 --users 之后,一次不带旗的重跑会拿缺省 single 把多租部署的
31
31
  # REQUIRE_PRINCIPAL 翻回 false(kube-up 路径此前就同形)—— 事实由两只脚本各自在写凭据的同一处 resetk 落盘。
32
32
  # 调用方先 source lib/envf.sh 并定好 ENVF(文件可以还不存在 = 首装,无事实)。
33
33
  users_decide() {
@@ -14,7 +14,7 @@
14
14
  default <users> 打印该租户形下的缺省 choice
15
15
  options <users> 每行一个 `ask` 选项串 `value:label[:infeasible=原因|建议]`
16
16
  check <choice> 只判「是不是 compose 路径上的在役词」(退役词 / 表外词 ⇒ 拒,与 resolve 同一只判据),
17
- 不打印;sema-up 在建工作目录之前拿它判 --sandbox 的形(S-621),租户形那一半留给 resolve
17
+ 不打印;sema-up 在建工作目录之前拿它判 --sandbox 的形,租户形那一半留给 resolve
18
18
  resolve <users> <choice> 校验并打印该车道要落 .env 的 `KEY=VALUE` 行(仅有值的键);
19
19
  必需但由运维自备的键名打印成 `#REQUIRED <NAME>` 注释行(「选了却没给」的早拒读它)
20
20
  choice-of <REMOTE_EXEC 值> 部署事实 → `--sandbox` 词的反查(决策 = 显式旗 ∨ 部署事实 ∨ 表缺省):上一次落下的 `REMOTE_EXEC=<值>`
@@ -0,0 +1,42 @@
1
+ # lib/node-addrs.sh — 「集群节点有哪些地址」的唯一读法(kube-up 用;输入 = `kubectl get nodes -o json` 的体)。
2
+ #
3
+ # 两个读数,同读一份节点表(一次 kubectl):
4
+ # · node_primary_ip —— 第一只节点的第一只 InternalIP:NodePort 入口(Gitea 克隆地址、OAuth 回调、summary 里的访问地址);
5
+ # · node_cidrs_json —— 全部节点的全部 IPv4 InternalIP / ExternalIP,各成 /32,去重保序,打印成 JSON 数组:沙箱出网策略
6
+ # `sandbox.networkPolicy.nodeCidrs`。IPv6 地址不列 —— 策略不写 IPv6 放行规则,v6 地址无可再拒。
7
+ # 读不出 / 零地址 ⇒ 非 0 退出、stdout 空(调用方 die,不渲一份漏了节点的策略)。
8
+ _node_addrs_py() { # _node_addrs_py <primary|cidrs> (stdin = 节点表 JSON)
9
+ python3 -c 'import ipaddress, json, sys
10
+ mode = sys.argv[1]
11
+ try:
12
+ items = json.load(sys.stdin).get("items")
13
+ except Exception:
14
+ sys.exit(2)
15
+ if not isinstance(items, list):
16
+ sys.exit(2)
17
+ def addrs(node, kinds):
18
+ out = []
19
+ for a in ((node or {}).get("status") or {}).get("addresses") or []:
20
+ if isinstance(a, dict) and a.get("type") in kinds and isinstance(a.get("address"), str):
21
+ try:
22
+ out.append(ipaddress.ip_address(a["address"]))
23
+ except ValueError:
24
+ pass
25
+ return out
26
+ if mode == "primary":
27
+ first = addrs(items[0], ("InternalIP",)) if items else []
28
+ if not first:
29
+ sys.exit(3)
30
+ print(first[0])
31
+ else:
32
+ seen = []
33
+ for n in items:
34
+ for ip in addrs(n, ("InternalIP", "ExternalIP")):
35
+ if ip.version == 4 and f"{ip}/32" not in seen:
36
+ seen.append(f"{ip}/32")
37
+ if not seen:
38
+ sys.exit(3)
39
+ print(json.dumps(seen))' "$1"
40
+ }
41
+ node_primary_ip() { printf '%s' "$1" | _node_addrs_py primary; }
42
+ node_cidrs_json() { printf '%s' "$1" | _node_addrs_py cidrs; }
@@ -80,7 +80,7 @@ def main(path):
80
80
 
81
81
  emit("PROFILE", top.get("profile"))
82
82
  emit("REGION", top.get("region", "auto"))
83
- # S-600(codex 一轮 [high]):不写 users 就**不发射** —— 修前缺省发射 single,等于替运维表了态,sema-up 于是把它当显式旗,
83
+ # codex 一轮 [high]:不写 users 就**不发射** —— 修前缺省发射 single,等于替运维表了态,sema-up 于是把它当显式旗,
84
84
  # 盖掉 `.env` 里上一次落下的部署事实(多租部署不带旗重跑 ⇒ 被降成单用户,或撞事实冲突拒)。缺省归 sema-up 的决策
85
85
  # (显式旗 ∨ 部署事实 ∨ 表缺省 single),不在解析器里另立一份。
86
86
  emit("USERS", top.get("users"))
@@ -104,7 +104,7 @@ def main(path):
104
104
  emit("DP_S3", dp.get("s3", "deploy"))
105
105
  emit("DP_BACKUP", dp.get("backup", "true"))
106
106
  sb = sections.get("sandbox", {})
107
- # S-599:`sandbox.lane` 是**死词**,已删。machines.yaml 只走 kube 路径,而 kube-up.sh 的 runtime
107
+ # `sandbox.lane` 是**死词**,已删。machines.yaml 只走 kube 路径,而 kube-up.sh 的 runtime
108
108
  # 是按 runtimeClass `kata-qemu` 在不在自动定的(kube-up.sh:94-96),从来不读 SANDBOX_LANE ——
109
109
  # 发射它只会让运维以为自己选到了什么。**响亮拒**而不是静默忽略:一个设了却没有任何效果的旋钮,
110
110
  # 正是本批要消灭的那类病(留着它,下一个人还会照模板填)。
@@ -1,4 +1,4 @@
1
- # lib/shell-access.sh — 「壳(sema CLI)怎么接这台引擎」的唯一渲染(S-850,7.104.0)。sema-up.sh(汇总 / dry-run 计划 /
1
+ # lib/shell-access.sh — 「壳(sema CLI)怎么接这台引擎」的唯一渲染(7.104.0)。sema-up.sh(汇总 / dry-run 计划 /
2
2
  # `--interactive=json` 的 summary)、kube-up.sh、cluster-up.sh 三条部署路径都调它,不各写一份。
3
3
  # 只给**位置**、不给值:令牌在哪只文件的哪个键、在壳里放进哪个变量 —— 本文件的函数不读任何凭据。
4
4
  #
@@ -17,9 +17,9 @@ done
17
17
  HERE="$(cd "$(dirname "$_self")" && pwd)"
18
18
  unset _self _hops _dir
19
19
  # <<< 自身目录
20
- # 自动数据根的路径形只在 lib/dataroot.sh 定义一次(S-851):下面「多盘机」建议句与 sema-up 自动选的根同一条规则。
20
+ # 自动数据根的路径形只在 lib/dataroot.sh 定义一次:下面「多盘机」建议句与 sema-up 自动选的根同一条规则。
21
21
  . "$HERE/lib/dataroot.sh"
22
- # 取值旗的形(S-621):判据与词表同 sema-up.sh 一处定义。
22
+ # 取值旗的形:判据与词表同 sema-up.sh 一处定义。
23
23
  . "$HERE/lib/flagshape.sh"
24
24
  log() { printf '[preflight] %s\n' "$*" >&2; }
25
25
 
@@ -36,7 +36,7 @@ for a in "$@"; do
36
36
  --project=*) PROJECT="${a#--project=}" ;;
37
37
  esac
38
38
  done
39
- # 取值旗的形(S-621)——在任何探测之前(本脚本只读,但 --json 的 profile 原样进协议行、端口原样进 ss / lsof 的参数)。
39
+ # 取值旗的形——在任何探测之前(本脚本只读,但 --json 的 profile 原样进协议行、端口原样进 ss / lsof 的参数)。
40
40
  # profile:sema-up 传它自己的档位词;单独跑的缺省是 full(= 非 data-center 的阈值)。
41
41
  flag_enum "--profile" "$PROFILE" full $FLAG_WORDS_PROFILE
42
42
  flag_project "--project" "$PROJECT"
@@ -122,7 +122,7 @@ if [ -n "$BEST_MNT" ] && [ "$BEST_MNT" != "/" ] && [ "$BEST_GB" -gt "${DISK_GB:-
122
122
  add WARN disk-alt "$BEST_MNT ${BEST_GB}G avail" "存在比 / 更大的数据盘(多盘机)" "--data-root=$(dataroot_for_disk "$BEST_MNT" "$PROJECT")(sema-up 未显式指定时会自动选它;数据根按项目分)"
123
123
  fi
124
124
 
125
- # ── KVM(**kube 路径**的 kata runtimeClass 前提;compose 路径已无需要 KVM 的车道,S-599)────────
125
+ # ── KVM(**kube 路径**的 kata runtimeClass 前提;compose 路径已无需要 KVM 的车道)────────
126
126
  # 有 KVM ⇒ 走 full-cluster 时 kata-deploy 能装上,沙箱得 VM 级隔离;没有 ⇒ kube 路径退 runc 容器
127
127
  # 隔离(仍是真隔离,只是弱于 VM)。两种都不是 BLOCK:单机 compose 路径的车道(host / e2b-cloud)
128
128
  # 与 KVM 无关。