@sema-agent/server 7.151.0 → 7.152.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.
- package/MIGRATION.md +266 -0
- package/README.md +15 -3
- package/README.zh-CN.md +10 -2
- package/USAGE.md +93 -64
- package/deploy/sema-up/README.md +5 -4
- package/deploy/sema-up/cluster-up.sh +6 -6
- package/deploy/sema-up/kube-up.sh +5 -5
- package/deploy/sema-up/lib/flagshape.sh +36 -8
- package/deploy/sema-up/machines.example.yaml +3 -1
- package/deploy/sema-up/sema-up.sh +22 -16
- package/dist/approval-ask-audit-store.d.ts +1 -1
- package/dist/approval-ask-machine.d.ts +4 -10
- package/dist/approval-ask-retention.d.ts +1 -1
- package/dist/approval-card.d.ts +10 -12
- package/dist/approval-gate-currency.d.ts +8 -8
- package/dist/approval-gate-currency.js +3 -4
- package/dist/approval-hmac.d.ts +17 -1
- package/dist/approval-hmac.js +7 -1
- package/dist/approval-queue-kind.d.ts +1 -1
- package/dist/approval.d.ts +2 -2
- package/dist/approval.js +2 -2
- package/dist/bind-host.d.ts +1 -3
- package/dist/bind-host.js +2 -3
- package/dist/boot/coordinators.d.ts +1 -1
- package/dist/boot/coordinators.js +9 -10
- package/dist/boot/device-lane.js +2 -0
- package/dist/boot/execution-env.d.ts +1 -0
- package/dist/boot/execution-env.js +31 -5
- package/dist/boot/leader.d.ts +31 -30
- package/dist/boot/leader.js +38 -28
- package/dist/boot/leg-path-adjudication.d.ts +40 -0
- package/dist/boot/leg-path-adjudication.js +18 -0
- package/dist/boot/parked-revive-gate.js +3 -15
- package/dist/boot/reapers.d.ts +1 -1
- package/dist/boot/reapers.js +1 -1
- package/dist/boot/resolve-spec.js +12 -26
- package/dist/boot/runner-deps.d.ts +39 -35
- package/dist/boot/runner-deps.js +92 -89
- package/dist/boot/shutdown.d.ts +6 -0
- package/dist/boot/shutdown.js +10 -4
- package/dist/boot/stage-02-web-admin-pull.js +4 -5
- package/dist/boot/stage-05-execution-env.js +2 -1
- package/dist/boot/stage-06-runners.d.ts +2 -0
- package/dist/boot/stage-06-runners.js +10 -4
- package/dist/boot/stage-07-capability-layer.d.ts +1 -0
- package/dist/boot/stage-07-capability-layer.js +1 -1
- package/dist/boot/stage-08-reapers.d.ts +1 -0
- package/dist/boot/stage-09-leader.d.ts +1 -0
- package/dist/boot/stage-09-leader.js +2 -2
- package/dist/boot/stage-10-http-server.d.ts +8 -0
- package/dist/boot/stage-10-http-server.js +11 -15
- package/dist/boot/stores.js +7 -4
- package/dist/boot/web-admin.js +2 -7
- package/dist/capabilities/approvals-push.d.ts +3 -3
- package/dist/capabilities/scenarios.d.ts +28 -13
- package/dist/capabilities/scenarios.js +2 -2
- package/dist/capability-facts.d.ts +22 -20
- package/dist/capability-facts.js +18 -34
- package/dist/card-rule-offers.d.ts +32 -0
- package/dist/card-rule-offers.js +130 -0
- package/dist/config-catalog.js +12 -11
- package/dist/config-dir-trust.js +4 -2
- package/dist/config-invariants.d.ts +18 -7
- package/dist/config-invariants.js +51 -8
- package/dist/config-lkg.d.ts +5 -19
- package/dist/config-lkg.js +8 -62
- package/dist/config-provider.d.ts +1 -1
- package/dist/config-root-migration.d.ts +2 -2
- package/dist/config-types.d.ts +28 -38
- package/dist/config.d.ts +7 -5
- package/dist/config.js +55 -16
- package/dist/control-socket.d.ts +51 -0
- package/dist/control-socket.js +115 -0
- package/dist/deployment-governance.d.ts +2 -1
- package/dist/device-ws-hub.d.ts +7 -0
- package/dist/device-ws-hub.js +7 -1
- package/dist/elicitation.js +2 -2
- package/dist/entry-problems.d.ts +40 -3
- package/dist/entry-problems.js +3 -1
- package/dist/execution-env-refusal.d.ts +8 -2
- package/dist/execution-env-refusal.js +3 -0
- package/dist/fleet/engine-signal.d.ts +12 -29
- package/dist/fleet/engine-signal.js +1 -7
- package/dist/fleet-client.js +2 -5
- package/dist/gate-settlement.d.ts +1 -8
- package/dist/gate-settlement.js +0 -4
- package/dist/history-anchor.js +1 -1
- package/dist/hitl-delivery.d.ts +2 -3
- package/dist/hitl-delivery.js +0 -2
- package/dist/hooks/hook-llm.js +4 -2
- package/dist/hooks/hook-runner.d.ts +3 -2
- package/dist/hooks/hook-runner.js +16 -1
- package/dist/host-decision.d.ts +11 -11
- package/dist/http/active-run-conflict.d.ts +35 -2
- package/dist/http/active-run-conflict.js +48 -19
- package/dist/http/approval-sweeps.d.ts +1 -1
- package/dist/http/approval-sweeps.js +5 -2
- package/dist/http/checkpoint-ctx.d.ts +2 -0
- package/dist/http/checkpoint-ctx.js +1 -0
- package/dist/http/dispatch.d.ts +6 -2
- package/dist/http/dispatch.js +25 -5
- package/dist/http/durable-run-leg.js +0 -1
- package/dist/http/health-reader.d.ts +16 -9
- package/dist/http/health-reader.js +2 -1
- package/dist/http/health-self-report.js +1 -1
- package/dist/http/owner-access.d.ts +2 -3
- package/dist/http/owner-access.js +3 -4
- package/dist/http/principal-gate.d.ts +49 -21
- package/dist/http/principal-gate.js +61 -11
- package/dist/http/request-channel.d.ts +23 -0
- package/dist/http/request-channel.js +9 -0
- package/dist/http/request-guards.js +17 -2
- package/dist/http/resume-ctx-read.js +20 -3
- package/dist/http/resume-legs.d.ts +2 -2
- package/dist/http/resume-legs.js +111 -41
- package/dist/http/route-ctx.d.ts +73 -7
- package/dist/http/route-ctx.js +17 -0
- package/dist/http/route-table.d.ts +4 -0
- package/dist/http/route-table.js +4 -0
- package/dist/http/routes/admin-config-refresh.js +3 -3
- package/dist/http/routes/admin-drain.d.ts +3 -0
- package/dist/http/routes/admin-drain.js +7 -7
- package/dist/http/routes/admin-memory-optout.js +3 -3
- package/dist/http/routes/adoption.js +3 -5
- package/dist/http/routes/approvals-assistant.d.ts +2 -1
- package/dist/http/routes/approvals-assistant.js +95 -48
- package/dist/http/routes/capabilities.d.ts +4 -0
- package/dist/http/routes/capabilities.js +30 -5
- package/dist/http/routes/config-catalog.js +2 -2
- package/dist/http/routes/devices.js +1 -1
- package/dist/http/routes/diagnostics.d.ts +3 -3
- package/dist/http/routes/diagnostics.js +19 -7
- package/dist/http/routes/images.js +10 -10
- package/dist/http/routes/memory-bundle.js +3 -3
- package/dist/http/routes/memory-compliance.js +3 -3
- package/dist/http/routes/memory-consolidation.js +2 -2
- package/dist/http/routes/memory-origin.js +3 -3
- package/dist/http/routes/memory-policy.js +2 -2
- package/dist/http/routes/observability.js +3 -3
- package/dist/http/routes/retention-ops.js +3 -3
- package/dist/http/routes/rules.js +5 -5
- package/dist/http/routes/run-permission-mode.d.ts +2 -1
- package/dist/http/routes/run-permission-mode.js +2 -2
- package/dist/http/routes/runs.d.ts +4 -9
- package/dist/http/routes/runs.js +73 -33
- package/dist/http/routes/session-sync.d.ts +18 -6
- package/dist/http/routes/session-sync.js +38 -36
- package/dist/http/routes/sessions.js +20 -9
- package/dist/http/routes/tasks.js +28 -37
- package/dist/http/routes/workflows.js +1 -1
- package/dist/http/server.d.ts +9 -3
- package/dist/http/server.js +15 -3
- package/dist/http/submit-ctx.d.ts +1 -1
- package/dist/http/submit-ctx.js +2 -0
- package/dist/human-facing-args.d.ts +33 -0
- package/dist/human-facing-args.js +33 -0
- package/dist/index.d.ts +1 -1
- package/dist/k8s-api-credentials.d.ts +29 -0
- package/dist/k8s-api-credentials.js +25 -0
- package/dist/lane-home-probe.d.ts +1 -1
- package/dist/lane-home-probe.js +2 -1
- package/dist/leader/diffup.d.ts +19 -0
- package/dist/leader/diffup.js +7 -0
- package/dist/leader/leader.d.ts +114 -10
- package/dist/leader/leader.js +69 -5
- package/dist/leader/repair-wire.js +2 -2
- package/dist/leader/run-entry.d.ts +2 -1
- package/dist/leader/run-entry.js +1 -1
- package/dist/leader/wire.d.ts +42 -132
- package/dist/leader/wire.js +81 -67
- package/dist/memory-scope.d.ts +20 -9
- package/dist/memory-scope.js +15 -3
- package/dist/model-entry-headers.d.ts +9 -10
- package/dist/model-entry-headers.js +0 -4
- package/dist/model-entry-refusal.d.ts +7 -4
- package/dist/model-entry-refusal.js +11 -5
- package/dist/model-plane-face.d.ts +1 -1
- package/dist/model-plane-face.js +3 -1
- package/dist/model-route-endpoint.d.ts +13 -7
- package/dist/model-route-endpoint.js +14 -11
- package/dist/model-select.d.ts +22 -0
- package/dist/model-select.js +9 -0
- package/dist/model-unreachable-notice.d.ts +11 -0
- package/dist/model-unreachable-notice.js +4 -4
- package/dist/object-store-buckets.d.ts +640 -6
- package/dist/object-store-buckets.js +166 -0
- package/dist/observability/fail-open.d.ts +20 -16
- package/dist/observability/fail-open.js +20 -16
- package/dist/observability/logger.js +3 -1
- package/dist/operator-roster.d.ts +68 -0
- package/dist/operator-roster.js +32 -0
- package/dist/orchestration/workflow-park-decision.d.ts +1 -1
- package/dist/outbound-dispatcher.d.ts +71 -8
- package/dist/outbound-dispatcher.js +48 -7
- package/dist/owner-faces.d.ts +1 -1
- package/dist/parked-decide.d.ts +2 -2
- package/dist/permission-mode-admission.d.ts +59 -26
- package/dist/permission-mode-admission.js +37 -10
- package/dist/plugins/approval-ask-store-file.d.ts +4 -0
- package/dist/plugins/approval-ask-store-file.js +3 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +4 -0
- package/dist/plugins/approval-ask-store-memory.js +7 -1
- package/dist/plugins/approval-ask-store-sql.d.ts +26 -2
- package/dist/plugins/approval-ask-store-sql.js +12 -1
- package/dist/plugins/blob-backend.d.ts +83 -7
- package/dist/plugins/blob-backend.js +57 -6
- package/dist/plugins/checkpoint-index-columns.d.ts +20 -16
- package/dist/plugins/checkpoint-index-columns.js +3 -6
- package/dist/plugins/checkpoint-store-face.d.ts +119 -61
- package/dist/plugins/checkpoint-store-face.js +134 -55
- package/dist/plugins/landed-attendants.d.ts +2 -2
- package/dist/plugins/local-checkpoint-store.d.ts +13 -3
- package/dist/plugins/local-checkpoint-store.js +38 -49
- package/dist/plugins/one-time-migrations.d.ts +51 -21
- package/dist/plugins/one-time-migrations.js +67 -45
- package/dist/plugins/pg-pool.js +11 -9
- package/dist/plugins/remote-env-host.d.ts +29 -10
- package/dist/plugins/remote-env-host.js +99 -19
- package/dist/plugins/remote-env-k8s.d.ts +68 -2
- package/dist/plugins/remote-env-k8s.js +107 -24
- package/dist/plugins/replica-registration.d.ts +1 -1
- package/dist/plugins/replica-registration.js +1 -1
- package/dist/plugins/s3-presign.d.ts +23 -0
- package/dist/plugins/s3-presign.js +37 -3
- package/dist/plugins/scheduler-support.d.ts +2 -2
- package/dist/plugins/scheduler-support.js +0 -3
- package/dist/plugins/schema-indexes.js +2 -0
- package/dist/plugins/send-file-ledger.d.ts +2 -2
- package/dist/plugins/send-file-ledger.js +2 -2
- package/dist/plugins/send-user-file.d.ts +3 -4
- package/dist/plugins/send-user-file.js +56 -52
- package/dist/plugins/session-blob-claim-token.d.ts +15 -0
- package/dist/plugins/session-blob-claim-token.js +20 -0
- package/dist/plugins/session-blob-namespace.d.ts +46 -0
- package/dist/plugins/session-blob-namespace.js +116 -0
- package/dist/plugins/snapshot-bucket-presence.d.ts +25 -2
- package/dist/plugins/snapshot-bucket-presence.js +8 -2
- package/dist/plugins/sql-json-column.d.ts +1 -1
- package/dist/plugins/store-backend.d.ts +44 -2
- package/dist/plugins/store-backend.js +75 -53
- package/dist/plugins/task-attachment-store.d.ts +2 -1
- package/dist/plugins/task-attachment-store.js +5 -1
- package/dist/plugins/tidb-pool.js +19 -24
- package/dist/plugins/workspace-custody.d.ts +4 -3
- package/dist/question.d.ts +2 -1
- package/dist/question.js +5 -13
- package/dist/request-form.d.ts +6 -1
- package/dist/request-form.js +4 -1
- package/dist/rule-issue-reading.d.ts +1 -1
- package/dist/rules-consent.d.ts +1 -1
- package/dist/run-local.js +8 -9
- package/dist/runs.d.ts +17 -8
- package/dist/runs.js +15 -2
- package/dist/runtime-governance.d.ts +2 -2
- package/dist/sema-config-dir.d.ts +2 -1
- package/dist/session-sync.d.ts +27 -11
- package/dist/session-sync.js +15 -7
- package/dist/stores-sql/blob-index-sql.d.ts +30 -9
- package/dist/stores-sql/blob-index-sql.js +40 -21
- package/dist/stores-sql/checkpoint-store-sql.d.ts +54 -27
- package/dist/stores-sql/checkpoint-store-sql.js +70 -146
- package/dist/stores-sql/file-history-store-sql.d.ts +64 -16
- package/dist/stores-sql/file-history-store-sql.js +100 -28
- package/dist/stores-sql/retention-store-sql.js +3 -9
- package/dist/task-settings.d.ts +6 -5
- package/dist/task-settings.js +3 -3
- package/dist/tool-approval.d.ts +342 -518
- package/dist/tool-approval.js +498 -1207
- package/dist/trace/core-keyset-guard.d.ts +1 -1
- package/dist/trace/ledger-events.d.ts +3 -3
- package/dist/trace/project.d.ts +2 -3
- package/dist/trace/redact.js +3 -2
- package/dist/trace/self-minted-wire.d.ts +287 -157
- package/dist/trace/self-minted-wire.js +93 -48
- package/dist/web-admin-client/apply-effective.js +2 -2
- package/dist/web-admin-client/read-warnings.d.ts +2 -2
- package/dist/web-admin-client/read-warnings.js +1 -1
- package/dist/web-admin-client/types.d.ts +1 -1
- package/dist/workspace-space.d.ts +10 -4
- package/dist/workspace-space.js +4 -1
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +1 -1
- package/package.json +6 -2
- package/scripts/embed-minimal.mjs +3 -3
- package/wire-changes/server@7.152.0.json +900 -0
- package/dist/config-d-migration.d.ts +0 -37
- package/dist/config-d-migration.js +0 -60
|
@@ -18,26 +18,54 @@
|
|
|
18
18
|
# ── 词表(单一属主)──────────────────────────────────────────────────────────────────────────────
|
|
19
19
|
FLAG_WORDS_PROFILE="full-single data-center local-plus full-cluster"
|
|
20
20
|
FLAG_WORDS_USERS="single multi"
|
|
21
|
+
# 租户形的释义 —— 拒句(flag_users_required)按词表逐词取,与词表同批改(词表加一个词而这里没有它 ⇒ 拒句生成处非零退出,不静默少一条出路)。
|
|
22
|
+
users_gloss() {
|
|
23
|
+
case "$1" in
|
|
24
|
+
single) printf '%s' "只给一个人用:这台部署的每个调用方都是它的运维,身份隔离关" ;;
|
|
25
|
+
multi) printf '%s' "被不止一个人调用(团队):身份隔离开,运维由具名名单 OPERATOR_PRINCIPALS 另给" ;;
|
|
26
|
+
*) return 1 ;;
|
|
27
|
+
esac
|
|
28
|
+
}
|
|
21
29
|
# 租户形 ⇒ 容器上 REQUIRE_PRINCIPAL 的值 —— 这条翻译的**唯一**定义(7.105.0 从 sema-up.sh 搬来):sema-up 的 compose 生成段 /
|
|
22
30
|
# 事实核对,kube-up 的 helm values,cluster-up 的渲染清单与 helm values 同调这一只(修前 kube-up 另写一份同义翻译;
|
|
23
|
-
# cluster-up 一份都没有 ⇒ --users=multi 在 --kube=machines 路径上被静默丢成单用户)
|
|
24
|
-
|
|
31
|
+
# cluster-up 一份都没有 ⇒ --users=multi 在 --kube=machines 路径上被静默丢成单用户)。**闭集**:只认 single / multi 两词,
|
|
32
|
+
# 别的词(含空串)⇒ 非零退出、零输出 —— 不再有「认不出的词当 single」那一臂(缺省派生藏在翻译里,就是部署脚本替部署选了人数)。
|
|
33
|
+
principal_of_users() { case "$1" in multi) echo true ;; single) echo false ;; *) return 1 ;; esac; }
|
|
25
34
|
# 租户形 ⇒ 单用户运维声明 OPERATOR_SINGLE_USER 的值(唯一定义;三只脚本 / 渲染段同调):server 装配运维面时要单用户部署说出谁是运维,
|
|
26
35
|
# 不声明不起服(声明与具名名单 OPERATOR_PRINCIPALS 二选一;本工具渲前者)。single = 这台只有一个人 ⇒ 他就是运维(true);
|
|
27
|
-
# multi = 多租,运维由具名名单另给 ⇒ 不声明(false;多租形上声明本身会被 server 拒)
|
|
28
|
-
|
|
36
|
+
# multi = 多租,运维由具名名单另给 ⇒ 不声明(false;多租形上声明本身会被 server 拒)。同样是闭集(别的词 / 空串 ⇒ 非零、零输出)。
|
|
37
|
+
# 这句翻译只翻**部署自己给的那一词**(`--users` / `-f` 配置 / 这台部署上一次落下的事实 / 向导里人答的那一句);词没有给 ⇒ 过不到这里(见 users_decide /
|
|
38
|
+
# flag_users_required)。helm 图表不派生它:kube-up / cluster-up 的 helm 路径把这一句的结果写进 values 的 server.operatorSingleUser。
|
|
39
|
+
operator_single_user_of_users() { case "$1" in single) echo true ;; multi) echo false ;; *) return 1 ;; esac; }
|
|
40
|
+
# flag_users_required <称呼> —— `--users`(几个人用)**必填,没有缺省**:这一词是部署自己的声明,部署脚本 / 模板不替它选。缺省 single 会让
|
|
41
|
+
# 用模板起团队集群又忘设人数的部署每个调用方都成运维(服务端拒句里「不止一个人调用 ⇒ 设 REQUIRE_PRINCIPAL」那一道人判,对用脚本的人永远不出现);
|
|
42
|
+
# 缺省 multi 同样是替部署选(替单人部署开身份隔离)。拒 = log 两行 + exit 1。**拒句只在这里写一次**(sema-up / kube-up / cluster-up 同调;词从
|
|
43
|
+
# FLAG_WORDS_USERS 取,释义从 users_gloss 取),与随包 helm 图表的「两键都没设 ⇒ 渲染即拒」同一律同一组出路。
|
|
44
|
+
flag_users_required() {
|
|
45
|
+
local w g out=""
|
|
46
|
+
for w in $FLAG_WORDS_USERS; do
|
|
47
|
+
g="$(users_gloss "$w")" || { log "⛔ 内部不一致:租户词 $w 在 FLAG_WORDS_USERS 里却没有释义 —— 词表与 users_gloss 要同批改"; exit 1; }
|
|
48
|
+
out="${out:+$out / }--users=$w($g)"
|
|
49
|
+
done
|
|
50
|
+
log "⛔ $1 没给 —— 几个人用是这台部署自己的声明:部署脚本不替你选(缺省 single = 忘设人数的团队集群每个调用方都成运维;缺省 multi = 替单人部署开身份隔离)"
|
|
51
|
+
log " ↳ 下一步(二选一):$out;kube-up.sh / cluster-up.sh 单独跑时同一个词写成环境变量 USERS=<词>"
|
|
52
|
+
exit 1
|
|
53
|
+
}
|
|
29
54
|
|
|
30
55
|
# users_decide <显式给了 USERS 吗(1 / 空)> —— kube 两条装配路径(kube-up / cluster-up)的租户形决策,与 sema-up 的
|
|
31
|
-
# compose 档同一条规则:**决策 = 显式 USERS ∨ 上一次落在 $ENVF 的部署事实 REQUIRE_PRINCIPAL
|
|
32
|
-
#
|
|
56
|
+
# compose 档同一条规则:**决策 = 显式 USERS ∨ 上一次落在 $ENVF 的部署事实 REQUIRE_PRINCIPAL;都没有 ⇒ 拒(flag_users_required,没有缺省)**;
|
|
57
|
+
# 显式值与事实不一致 ⇒ 拒并点名两处(不静默把一台多租部署降成单用户,也不静默把单用户升成多租)。事实 → 租户词只经
|
|
33
58
|
# principal_of_users 反查(两词逐个过正向比,不另写反表);认不出的事实值 ⇒ 拒。设 USERS。
|
|
34
59
|
# codex 一轮 [high]:machines 路径开始认 --users 之后,一次不带旗的重跑会拿缺省 single 把多租部署的
|
|
35
|
-
# REQUIRE_PRINCIPAL 翻回 false(kube-up 路径此前就同形)—— 事实由两只脚本各自在写凭据的同一处 resetk
|
|
60
|
+
# REQUIRE_PRINCIPAL 翻回 false(kube-up 路径此前就同形)—— 事实由两只脚本各自在写凭据的同一处 resetk 落盘;缺省 single 本身随后退役(没有缺省)。
|
|
36
61
|
# 调用方先 source lib/envf.sh 并定好 ENVF(文件可以还不存在 = 首装,无事实)。
|
|
37
62
|
users_decide() {
|
|
38
63
|
local given="$1" fact fact_users="" u
|
|
39
64
|
fact="$(envf_get REQUIRE_PRINCIPAL)" || exit 1
|
|
40
|
-
[ -
|
|
65
|
+
if [ -z "$fact" ]; then
|
|
66
|
+
[ -n "$given" ] || flag_users_required "--users(USERS)"
|
|
67
|
+
return 0
|
|
68
|
+
fi
|
|
41
69
|
for u in $FLAG_WORDS_USERS; do [ "$(principal_of_users "$u")" = "$fact" ] && fact_users="$u"; done
|
|
42
70
|
if [ -z "$fact_users" ]; then
|
|
43
71
|
log "⛔ 部署事实 $ENVF 里 REQUIRE_PRINCIPAL=$(flag_show "$fact"):本工具只读自己写出的两形 $(principal_of_users multi) / $(principal_of_users single)"
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
# 凭据二选一:password(bootstrap 用它铺 ssh key,不落盘不入日志)或 ssh_key(已互信)。
|
|
4
4
|
profile: full-cluster # full-cluster | full-single | data-center | local-plus
|
|
5
5
|
region: auto # auto | cn | global(auto=连通性探测,--region 可覆盖)
|
|
6
|
-
users: single
|
|
6
|
+
# users: single|multi # 必填(这里不写缺省,也不替你选):几个人用是这台部署自己的声明。取消注释写一个,或每次带 sema-up 的 --users=<词>;
|
|
7
|
+
# # single = 只给一个人用(每个调用方都是运维;超管 turnkey)| multi = 一个团队(身份隔离+能力默认全开,运维由具名名单另给)。
|
|
8
|
+
# # 重跑沿用 ~/.sema-up/<project>/.env 里上一次落下的,不必再写;都没有 ⇒ sema-up 拒并给两条出路。
|
|
7
9
|
# server_image: ghcr.io/sema-agent/sema-server:<tag> # 引擎镜像 registry 引用(GHCR/Docker Hub 公开仓,
|
|
8
10
|
# # 匿名可拉;CN 兜底=内网 Gitea registry。SWR 已弃用 2026-07-13);
|
|
9
11
|
# # 不填则要 env SEMA_SERVER_IMAGE 或 SEMA_SERVER_IMAGE_TAR(tar 预灌)
|
|
@@ -56,7 +56,7 @@ usage() {
|
|
|
56
56
|
cat "$HERE/lib/usage-head.txt"
|
|
57
57
|
# 闭集词表从 lib/flagshape.sh 渲(单一属主):加 / 删一个词,这几行自己跟着变
|
|
58
58
|
printf ' --profile=P %s\n' "$(printf '%s' "$FLAG_WORDS_PROFILE" | tr ' ' '|')"
|
|
59
|
-
printf ' --users=U %s\n' "$(printf '%s' "$FLAG_WORDS_USERS" | tr ' ' '|')"
|
|
59
|
+
printf ' --users=U %s(必填,没有缺省;重跑沿用 .env 里上一次落下的;data-center 档不装 agent,不用)\n' "$(printf '%s' "$FLAG_WORDS_USERS" | tr ' ' '|')"
|
|
60
60
|
printf ' --region=R %s\n' "$(printf '%s' "$FLAG_WORDS_REGION" | tr ' ' '|')"
|
|
61
61
|
cat "$HERE/lib/usage-flags.txt"
|
|
62
62
|
# 词表从 lib/lanes.json 渲(单一属主):加/删一条车道,这行自己跟着变
|
|
@@ -327,7 +327,7 @@ fi
|
|
|
327
327
|
"data-center:只装数据面(PG+MinIO+备份)——agent 在你自己机器上,数据放这里" \
|
|
328
328
|
"full-cluster:k8s 准生产——3 机 ssh 装配 / 已有集群 kubeconfig / 本机装 k3s" \
|
|
329
329
|
"local-plus:本机只跑 agent,连一个已经部署好的 data-center 数据面")
|
|
330
|
-
# ── 两个决策(租户形 / 车道)同一条规则:决策 = 显式旗 ∨ 部署事实 ∨ 表缺省 ─────────────────────
|
|
330
|
+
# ── 两个决策(租户形 / 车道)同一条规则:决策 = 显式旗 ∨ 部署事实 ∨ 表缺省 —— 租户形**没有表缺省**(见下)─────────────────────
|
|
331
331
|
# 「部署事实」= 同一只 `$WORK/.env`:compose 的 agent 档由本脚本写,full-cluster 由 kube-up / cluster-up 在写凭据的同一处
|
|
332
332
|
# 写(修前 kube 两条路径不落这条事实 ⇒ 不带旗重跑拿缺省 single 把多租部署降回单用户);data-center 不起 agent。事实 → 决策词只经属主翻译,本脚本不抄第二份:
|
|
333
333
|
# · REQUIRE_PRINCIPAL → --users:只认 sema-up 自己写出的两形 true / false(别的写法 ⇒ 拒;不复刻 server 的布尔词表);
|
|
@@ -335,18 +335,20 @@ fi
|
|
|
335
335
|
# 不带旗重跑 ⇒ 沿用事实(多租部署重跑不必再带 --users=multi);显式旗与事实不一致 ⇒ fact_conflict 拒并点名两处。
|
|
336
336
|
# 🔴 为什么缺省不能先于事实(合并复审两条真案):把表缺省当成意图去和事实比,合法的无旗重跑就被拒;
|
|
337
337
|
# 反过来若只比不拒,保留的多租 `.env` 在缺省 single 下会被车道表判成 host —— 容器拿到 REQUIRE_PRINCIPAL=true ∧ host。
|
|
338
|
+
# 🔴 租户形不取缺省(单用户声明由部署写,脚本不替它选):显式旗(`--users` / `-f` 配置)∨ 部署事实 ∨ 向导里人答的那一句,都没有 ⇒ 拒
|
|
339
|
+
# (`flag_users_required`,拒句与 kube-up / cluster-up 同一只判官)。缺省 single = 用模板起团队集群又忘设人数的部署人人是运维;缺省 multi 同样是
|
|
340
|
+
# 替部署选。data-center 档不装 agent,没有声明可言:不问、不拒(USERS 留空,汇总行写 n/a)。
|
|
338
341
|
# 租户形 ⇒ 容器上 REQUIRE_PRINCIPAL 的值:`principal_of_users`(lib/flagshape.sh,三只脚本共用的唯一定义;kube-up /
|
|
339
|
-
# cluster-up 也调它)。正向(生成段 setk、事实核对)与反向(事实 →
|
|
342
|
+
# cluster-up 也调它)。正向(生成段 setk、事实核对)与反向(事实 → 向导问句的缺省词)都经它:反向是拿两个租户词逐个过这只函数去比,
|
|
340
343
|
# 不另写一张反表(与车道的 `lanes choice-of` 同一姿势)。
|
|
341
|
-
USERS_DEF="
|
|
344
|
+
USERS_DEF="" RP_FACT="" RP_FACT_SRC="" REQUIRE_PRINCIPAL_WANT=""
|
|
342
345
|
case "$PROFILE" in
|
|
343
346
|
# full-cluster 也读 —— kube-up / cluster-up 在写凭据的同一处把 REQUIRE_PRINCIPAL 落进同一只 .env(它们自己
|
|
344
347
|
# 单独跑时也按同一条规则判,见 lib/flagshape.sh 的 users_decide)。
|
|
345
348
|
full-single|local-plus|full-cluster)
|
|
346
349
|
deploy_fact REQUIRE_PRINCIPAL; RP_FACT="$FACT_VAL" RP_FACT_SRC="$FACT_SRC"
|
|
347
350
|
if [ -n "$RP_FACT" ]; then
|
|
348
|
-
USERS_DEF=""
|
|
349
|
-
for _u in single multi; do [ "$(principal_of_users "$_u")" = "$RP_FACT" ] && USERS_DEF="$_u"; done
|
|
351
|
+
for _u in $FLAG_WORDS_USERS; do [ "$(principal_of_users "$_u")" = "$RP_FACT" ] && USERS_DEF="$_u"; done
|
|
350
352
|
if [ -z "$USERS_DEF" ]; then
|
|
351
353
|
log "⛔ 部署事实 REQUIRE_PRINCIPAL=$RP_FACT(来自 $RP_FACT_SRC):本脚本只读自己写出的两形 $(principal_of_users multi) / $(principal_of_users single)"
|
|
352
354
|
log " ↳ 下一步:改成 REQUIRE_PRINCIPAL=$(principal_of_users multi)(多人,身份隔离)或 REQUIRE_PRINCIPAL=$(principal_of_users single)(单人),再重跑"
|
|
@@ -354,13 +356,17 @@ case "$PROFILE" in
|
|
|
354
356
|
exit 1
|
|
355
357
|
fi
|
|
356
358
|
fi
|
|
359
|
+
if [ -z "$USERS" ]; then
|
|
360
|
+
# 无人值守没有人答 ⇒ 没有事实就没有词:拒。向导(tty / json)里问句的缺省只有事实词(重跑),没有事实 ⇒ 缺省为空,空答由 ask 的闭集句拒(同样列两词)。
|
|
361
|
+
if [ -z "$USERS_DEF" ] && [ "$MODE_INTERACTIVE" = "none" ]; then flag_users_required "--users(USERS)"; fi
|
|
362
|
+
USERS=$(ask users "几个人用?" "$USERS_DEF" "这是这台部署自己的声明,没有缺省(重跑沿用上一次落下的);单人可跳过全部权限配置,多人要开身份隔离" \
|
|
363
|
+
"single:就我一个(超级管理员 turnkey,零权限配置)" \
|
|
364
|
+
"multi:一个团队(身份隔离 ON,能力默认全开,之后可用 policy 收紧)")
|
|
365
|
+
fi
|
|
366
|
+
REQUIRE_PRINCIPAL_WANT="$(principal_of_users "$USERS")"
|
|
367
|
+
fact_conflict REQUIRE_PRINCIPAL "$RP_FACT" "$RP_FACT_SRC" "$REQUIRE_PRINCIPAL_WANT" "--users=$USERS"
|
|
357
368
|
;;
|
|
358
369
|
esac
|
|
359
|
-
[ -z "$USERS" ] && USERS=$(ask users "几个人用?" "$USERS_DEF" "单人可跳过全部权限配置,多人要开身份隔离" \
|
|
360
|
-
"single:就我一个(超级管理员 turnkey,零权限配置)" \
|
|
361
|
-
"multi:一个团队(身份隔离 ON,能力默认全开,之后可用 policy 收紧)")
|
|
362
|
-
REQUIRE_PRINCIPAL_WANT="$(principal_of_users "$USERS")"
|
|
363
|
-
fact_conflict REQUIRE_PRINCIPAL "$RP_FACT" "$RP_FACT_SRC" "$REQUIRE_PRINCIPAL_WANT" "--users=$USERS"
|
|
364
370
|
|
|
365
371
|
# registry:各档默认带上(clay 2026-07-12 拍;显式 --registry=false 可关)。
|
|
366
372
|
# local-plus 例外默认 false——它的数据面在远端,配置中心应随数据面部署,本机再起一个=两个配置中心。
|
|
@@ -544,7 +550,7 @@ HOSTIP=$(host_ip)
|
|
|
544
550
|
# test srv796 实测 NEW-5)。7.104.0 起REGISTRY_ENABLED 在建工作目录之前已过形判(只会是 true / false,或空 =
|
|
545
551
|
# 走档位缺省,缺省在上面已落定),registry 仍收成 on/off 决策词。region/profile/users/lane/git 到这里都已定死
|
|
546
552
|
# (形判在参数解析之后、交互答案在 ask() 里、车道在车道块)。
|
|
547
|
-
log "region=$REGION profile=$PROFILE users=$USERS sandbox=${SANDBOX_LANE:-n/a} lane=${LANE_REMOTE_EXEC:-n/a} registry=$([ "$REGISTRY_ENABLED" = "true" ] && echo on || echo off) git=$GIT_MODE"
|
|
553
|
+
log "region=$REGION profile=$PROFILE users=${USERS:-n/a} sandbox=${SANDBOX_LANE:-n/a} lane=${LANE_REMOTE_EXEC:-n/a} registry=$([ "$REGISTRY_ENABLED" = "true" ] && echo on || echo off) git=$GIT_MODE"
|
|
548
554
|
|
|
549
555
|
# ── 数据根(一条规则 —— 数据根归一个项目所有;判据全在 lib/dataroot.sh)───────────────────────────
|
|
550
556
|
# 取哪条根:`.env` 首装值(已装的项目不漂移,不搬数据)∨ --data-root / -f 的 DATA_ROOT ∨ 多盘机自动选大容量盘
|
|
@@ -616,7 +622,7 @@ fi
|
|
|
616
622
|
if $DRY_RUN; then
|
|
617
623
|
{
|
|
618
624
|
echo "══════ sema-up dry-run(不写文件、不起容器)══════"
|
|
619
|
-
echo " profile=$PROFILE users=$USERS region=$REGION registry=$REGISTRY_ENABLED git=$GIT_MODE"
|
|
625
|
+
echo " profile=$PROFILE users=${USERS:-n/a} region=$REGION registry=$REGISTRY_ENABLED git=$GIT_MODE"
|
|
620
626
|
echo " compose profiles: $COMPOSE_PROFILES(project=$PROJECT)"
|
|
621
627
|
echo " 凭据文件: $ENVF $([ -f "$ENVF" ] && echo '(已存在:只补缺,已有凭据不轮换)' || echo '(将新建,0600)')"
|
|
622
628
|
echo " 将执行:"
|
|
@@ -680,8 +686,8 @@ if [ "$PROFILE" = "full-single" ] || [ "$PROFILE" = "local-plus" ]; then
|
|
|
680
686
|
setk MODEL_ID "$MODEL"
|
|
681
687
|
[ -n "$MODEL_KEY" ] && setk MODEL_API_KEY "$MODEL_KEY"
|
|
682
688
|
setk REQUIRE_PRINCIPAL "$REQUIRE_PRINCIPAL_WANT"
|
|
683
|
-
#
|
|
684
|
-
#
|
|
689
|
+
# 单用户运维声明:由部署自己给的那一个租户词翻译(`--users` / 配置 / 上一次的事实 / 向导答案;缺了就在上面拒,没有缺省;lib/flagshape.sh 唯一定义),
|
|
690
|
+
# 每次重写 —— 它不是第二个部署事实,是 REQUIRE_PRINCIPAL 那一个事实的另一根键。不写 ⇒ 单用户 server 起服拒(没人能当运维);升级路径上旧 .env 没有这一行,resetk 补上。
|
|
685
691
|
resetk OPERATOR_SINGLE_USER "$(operator_single_user_of_users "$USERS")"
|
|
686
692
|
setk SANDBOX_PKG_SOURCE "$([ "$REGION" = "global" ] && echo global || echo '')"
|
|
687
693
|
[ -n "${SEMA_SERVER_IMAGE:-}" ] && setk SEMA_SERVER_IMAGE "$SEMA_SERVER_IMAGE"
|
|
@@ -1084,7 +1090,7 @@ else
|
|
|
1084
1090
|
echo " 数据卷 $(printf ',%s,' "$COMPOSE_PROFILES" | grep -q ',pg,' && printf '%s_pgdata ' "$PROJECT")$(printf ',%s,' "$COMPOSE_PROFILES" | grep -q ',s3,' && printf '%s_miniodata ' "$PROJECT")$([ "$REGISTRY_ENABLED" = "true" ] && printf '%s_registrydata ' "$PROJECT")$([ "$GIT_MODE" = "provision" ] && printf '%s_gitdata ' "$PROJECT")$(printf ',%s,' "$COMPOSE_PROFILES" | grep -q ',agent,' && printf '%s_sealedkey' "$PROJECT")$([ -n "$DATA_ROOT" ] && printf '(bind 落 %s)' "$DATA_ROOT")"
|
|
1085
1091
|
echo " 重入 再跑同命令=幂等升级(凭据不轮换);验证=smoke.sh --project=$PROJECT"
|
|
1086
1092
|
echo " 卸载 $0 --project=$PROJECT --teardown(留数据)/--teardown-volumes(连卷删)"
|
|
1087
|
-
[ "$PROFILE" = "data-center" ] && echo " 接入 别处 agent 连这个数据面 = sema-up.sh --profile=local-plus --pg-host=$HOSTIP --minio-endpoint=http://$HOSTIP:$MINIO_PORT + 两个密码(本机 .env 里)"
|
|
1093
|
+
[ "$PROFILE" = "data-center" ] && echo " 接入 别处 agent 连这个数据面 = sema-up.sh --profile=local-plus --users=<single|multi> --pg-host=$HOSTIP --minio-endpoint=http://$HOSTIP:$MINIO_PORT + 两个密码(本机 .env 里)"
|
|
1088
1094
|
echo "═══════════════════════════════════════════════════════════"
|
|
1089
1095
|
} >&2
|
|
1090
1096
|
fi
|
|
@@ -166,7 +166,7 @@
|
|
|
166
166
|
* 本店是协调器侧的审计 sink,不是跨后端 store 契约的一员(SQL 车道有真 ask 店,永不装本店)——
|
|
167
167
|
* 装配点在 `boot/coordinators.ts`(判据:`toolApprovalEnabled` ∧ `backend.kind === "local"` ∧
|
|
168
168
|
* `config.localDataRoot` 在场;真实 boot 恒铸 `localDataRoot`,缺席只发生在 stub-harness 上,判据
|
|
169
|
-
*
|
|
169
|
+
* 只填被测键的 harness 要的必然是「别碰真盘」)。root 与 `LocalBackend`
|
|
170
170
|
* 同源(`store-backend.ts:780` 的 `config.localDataRoot`),数据落 `<root>/approval-ask-audit/`。
|
|
171
171
|
*
|
|
172
172
|
* ## 体量与保留
|
|
@@ -6,19 +6,13 @@ export declare const ASK_TERMINAL: ReadonlySet<AskState>;
|
|
|
6
6
|
/** 批侧终态集合(无出边的 2 态)。 */
|
|
7
7
|
export declare const BATCH_TERMINAL: ReadonlySet<BatchState>;
|
|
8
8
|
/**
|
|
9
|
-
* [ref]:回决理由(`AskRow.decisionNote` → `decision_note` 列)
|
|
10
|
-
*
|
|
11
|
-
* 🔴 为什么住在这个模块:两个消费者分别是 durable 腿的 zod 体(`http/routes/runs.ts` 的
|
|
12
|
-
* `AskDecisionBodySchema`)与 live 腿的手写 parser(`tool-approval.ts` 的 `parseToolApprovalResponse`),
|
|
13
|
-
* 两处都在 ask 状态机的**同一张行**上写同一列。上限各写一份字面量 = 同一列上两个口径,而分歧只会在
|
|
14
|
-
* 「一条腿收下、另一条腿 400」的那天才被发现。本模块是两腿唯一的共同上游(askId/batchId 铸造与转移表
|
|
15
|
-
* 都在这里),放这里不引新依赖边。
|
|
9
|
+
* [ref]:回决理由(`AskRow.decisionNote` → `decision_note` 列)的字符上限 —— 列的口径住在行的状态机模块里(askId/batchId 铸造与转移表都在这里),
|
|
10
|
+
* 唯一的人决口(`http/routes/runs.ts` 的 `AskDecisionBodySchema`)读它。
|
|
16
11
|
*/
|
|
17
12
|
export declare const MAX_DECISION_NOTE_CHARS = 2048;
|
|
18
13
|
/**
|
|
19
|
-
* 回决回执上「理由记上了吗」(`noteRecorded`)一格的**唯一判官与唯一组句器** ——
|
|
20
|
-
*
|
|
21
|
-
* 回体(含 PARKED 行经停驻赎回受理的那一腿:停驻门受理之后决定记在这只问的行上,理由就在那一列)都经这两只函数说这件事,
|
|
14
|
+
* 回决回执上「理由记上了吗」(`noteRecorded`)一格的**唯一判官与唯一组句器** —— 决断口 `POST /v1/tasks/:taskId/asks/:askId/decision` 的每一个 200
|
|
15
|
+
* 回体(活卡首决 / 回放,与 PARKED 行经停驻赎回受理的那一腿:停驻门受理之后决定记在这只问的行上,理由就在那一列)都经这两只函数说这件事,
|
|
22
16
|
* 不在各自的回体字面量里手写第二份。
|
|
23
17
|
*
|
|
24
18
|
* 三态同一份契约:请求**没带** `note` ⇒ 键缺席(不是 `false`);带了 ⇒ `true | false`:`true` = **已确认**持久行上那段文本就是这次提交的
|
|
@@ -43,7 +43,7 @@ import type { BackgroundAgentRecord } from "@sema-agent/core";
|
|
|
43
43
|
export declare const APPROVAL_ASK_RETENTION_DEFAULT_MS: number;
|
|
44
44
|
/**
|
|
45
45
|
* 正值的下限:1 天(低于即钳到 1 天并点名)。还能动的 run 的问本来就不删(见文件头);下限管的是**刚结束**的 run:
|
|
46
|
-
* 客户端在 run 结束后还可能对它的卡做幂等重试 / 晚答(
|
|
46
|
+
* 客户端在 run 结束后还可能对它的卡做幂等重试 / 晚答(决断口对已决行同键回放首决、否则 409,对作废行 410,而不是 404),一天吸收这一段。
|
|
47
47
|
*/
|
|
48
48
|
export declare const APPROVAL_ASK_RETENTION_FLOOR_MS = 86400000;
|
|
49
49
|
/** 两次清扫之间的最短间隔(见文件头「节律」)。 */
|
package/dist/approval-card.d.ts
CHANGED
|
@@ -723,7 +723,7 @@ export type ApprovalCard = z.infer<typeof ApprovalCardSchema>;
|
|
|
723
723
|
* `schema_version` 列同值,列供 SQL 侧过滤,信封里这份供读面在解出内容**之前**判形)。
|
|
724
724
|
*
|
|
725
725
|
* `approvalId` = 这张卡**呈出时**的 wire 身份。7.133.0 起它恒等于行的键 `askId`(一只 ask 一只 wire 身份),本服务的活读者(重放帧 /
|
|
726
|
-
*
|
|
726
|
+
* 决断口 / 读口)一律读行的键、不读这一格;写它是给滚动升级窗里上一版的副本(它们的 strict 信封 schema 要求这一格并照它重放)。
|
|
727
727
|
* 唯一读这一格的是 local 车道的启动收敛 —— 拿它去审计账里查前世这只 ask 的成因:审计行记的就是当时呈出的那个 id
|
|
728
728
|
* (更早写下的行上是当年的登记本地 id)。
|
|
729
729
|
*
|
|
@@ -1032,8 +1032,8 @@ export declare function buildApprovalRequestFrame(input: {
|
|
|
1032
1032
|
* ({@link adoptStoredLiveFacts};行 = 真源)。带 NUL / 孤代理的一组不落座(某个后端存不下逐字的那一份,见 {@link buildApprovalCardEnvelope})。
|
|
1033
1033
|
* 卡面(`ApprovalCardSchema`)照旧不带这十一位(`approvalCard` 除外,见本注末段):
|
|
1034
1034
|
* 它们在帧顶层、不在 `card` 里,信封上是卡旁边的一座,不是卡的键。
|
|
1035
|
-
* `readRootCandidate` 随重放的射程与卡上 `ruleOffers` 同一句(`ApprovalCardSchema.ruleOffers` 顶注):回授经重放帧自己的 `
|
|
1036
|
-
*
|
|
1035
|
+
* `readRootCandidate` 随重放的射程与卡上 `ruleOffers` 同一句(`ApprovalCardSchema.ruleOffers` 顶注):回授经重放帧自己的 `askId` 走决断口的 live 形(体键 `readRootGrant`),
|
|
1036
|
+
* 有等待腿的副本兑得动;接管登记上没有等待腿,决定照收、目录不加;停驻形带它 ⇒ 400、没有等待腿可交(没有 `approval.read_root_granted` 通告 = 什么都没加)。
|
|
1037
1037
|
*
|
|
1038
1038
|
* `requiresRealApproval` 不在表里:卡上 `risk.requiresRealApproval` 是同一个事实(铸卡第三参就是它),一个事实一个读法。
|
|
1039
1039
|
* ⚠️ **`approvalCard` 是表里唯一一位 7.136.0 起同时在卡上的座**(`ApprovalCardSchema.approvalCard`:断连重放的卡要渲回同一张专卡,卡词必须进卡;
|
|
@@ -1054,9 +1054,8 @@ export declare function adoptStoredLiveFacts(frame: ApprovalRequestLiveFacts, se
|
|
|
1054
1054
|
/**
|
|
1055
1055
|
* [ref] §3.1 的呈卡帧(设计稿 §4.1 逐字)。
|
|
1056
1056
|
*
|
|
1057
|
-
* 🔴
|
|
1058
|
-
*
|
|
1059
|
-
* 一帧都不发;协议未上场的腿只发旧族。同一只 ask 在同一条腿上不再有两种开卡帧,消费方不再按 `approvalId` 去重。
|
|
1057
|
+
* 🔴 **审批只有这一个帧族**:一只 ask 的开卡 / 消卡 / 撤卡只走本族(`approval_request` / {@link ApprovalCompleteFrame} / {@link ApprovalRevokeFrame});
|
|
1058
|
+
* 呈卡协议不上场的 worker 不呈卡(问交无人值守政策口),没有回退发的另一族。
|
|
1060
1059
|
* 开卡的全部事实因此在本帧上:卡(`card`,耐久信封)+ 活面事实座({@link ApprovalRequestLiveFacts};活铸帧与重放帧同一份,见 {@link APPROVAL_REQUEST_LIVE_FACT_KEYS} 顶注)。
|
|
1061
1060
|
*/
|
|
1062
1061
|
export interface ApprovalRequestFrame extends ApprovalRequestLiveFacts {
|
|
@@ -1066,7 +1065,7 @@ export interface ApprovalRequestFrame extends ApprovalRequestLiveFacts {
|
|
|
1066
1065
|
* 活铸帧恒不带;行上有座的重放帧不带(座里缺的那一位就是真缺席)。不回填:存量行随窗到期收敛。
|
|
1067
1066
|
*/
|
|
1068
1067
|
liveFactsUnknown?: true;
|
|
1069
|
-
/** = SSE
|
|
1068
|
+
/** = SSE 具名事件名。 */
|
|
1070
1069
|
type: "approval_request";
|
|
1071
1070
|
schemaVersion: 1;
|
|
1072
1071
|
/** `deriveAskId` 派生(持久层主键;八元身份元组 —— 7.109.0 起含这一问的类集,7.143.0 起含展示的动作(工具名 + 入参摘要) —— 见 approval-ask-machine.ts)。 */
|
|
@@ -1082,22 +1081,21 @@ export interface ApprovalRequestFrame extends ApprovalRequestLiveFacts {
|
|
|
1082
1081
|
expiresAtMs: number;
|
|
1083
1082
|
serverNowMs: number;
|
|
1084
1083
|
/**
|
|
1085
|
-
* server 扩(不在设计字面)
|
|
1086
|
-
*
|
|
1084
|
+
* server 扩(不在设计字面):**恒等于 `askId`**(行的键就是这只 ask 唯一的 wire 身份;本族的消卡帧({@link ApprovalCompleteFrame})同带它)。
|
|
1085
|
+
* 7.152.0 起读它的两条口已删(决断口 / 读口按 `askId` 寻址),这一键只剩自指。
|
|
1087
1086
|
*/
|
|
1088
1087
|
approvalId: string;
|
|
1089
1088
|
}
|
|
1090
1089
|
/**
|
|
1091
1090
|
* 呈卡族的**单卡消卡帧**(`approval_complete`)—— 一只 ask 落定时发给每一条**收到过它的呈卡帧**的呈卡腿连接。
|
|
1092
1091
|
*
|
|
1093
|
-
*
|
|
1094
|
-
* `parked`),只是它属于本族:键与开卡帧对位(`askId` / `taskId` / `approvalId`,开卡帧上有的身份这里都有),消卡按开卡那一帧的键。
|
|
1092
|
+
* 一次 settle 的判决(`outcome` 三词、非人结局的 `cause`、park 路由的 `parked`):键与开卡帧对位(`askId` / `taskId` / `approvalId`,开卡帧上有的身份这里都有),消卡按开卡那一帧的键。
|
|
1095
1093
|
* 与 {@link ApprovalRevokeFrame} 的分工:撤卡帧是**批级**的(兄弟被赢家连坐成 `VOID` 的那一批,名单 = 那一次原子事务的行集,
|
|
1096
1094
|
* 不带逐卡终局);本帧是**单卡**的终局(人答 / 窗到期 / park 路由 / 取消 …)。同一只 ask 两帧都可能收到(被撤的兄弟自己的
|
|
1097
1095
|
* 登记也按 settle 收场)—— 按 `askId` 清卡即可,两帧不冲突。
|
|
1098
1096
|
*
|
|
1099
1097
|
* 投递 = 开卡帧的同一只腿传输(`hitl-delivery.ts`:先本 run 账本、再直写 —— sync 腿有 durable run 行时两只都有,bg / resume 腿只有账本)。
|
|
1100
|
-
* 门 = 这条连接上**接下过开卡帧的那几只 sink**(没见过开卡帧的 sink 收到消卡帧就是孤儿 close
|
|
1098
|
+
* 门 = 这条连接上**接下过开卡帧的那几只 sink**(没见过开卡帧的 sink 收到消卡帧就是孤儿 close;配对在竞速机一处)。
|
|
1101
1099
|
*/
|
|
1102
1100
|
export interface ApprovalCompleteFrame {
|
|
1103
1101
|
/** = SSE 具名事件名(同 `approval_request` 约定)。 */
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 一张停驻审批卡的「门」此刻还是不是它 ——
|
|
2
|
+
* 一张停驻审批卡的「门」此刻还是不是它 —— 续跑腿判 `approval_stale`(`/decide` 与决断口的停驻形都经它)与按问读口 `state` 的**同一只判官**。
|
|
3
3
|
*
|
|
4
4
|
* ## 病灶(为什么要有这一只)
|
|
5
5
|
* 问账行 `PARKED` 是终态(`approval-ask-machine.ts`:`PARKED: []`):赎回腿的单赢者是 **checkpoint 的 CAS**,取消腿动的也是 checkpoint(先 `expire` 门、再驱 run 终局),
|
|
6
6
|
* 两条腿都不改 ask 行的态(赎回受理之后只把决定记在行上,行仍 `PARKED`;门被引擎重开了行也不知道)。于是「这张卡的门还在不在」这件事只有 checkpoint 店知道;读口若只看行,就会在卡被答过 / run 被取消之后继续说 `parked` 并指路去决定,
|
|
7
|
-
*
|
|
7
|
+
* 而 7.151.x 及以前的应答口(7.152.0 起已删)对同一张卡早已答 `409 approval_stale`。同一件事两个读法 —— 本模块把它收成一个:读的是同一个问题、同一个来源。
|
|
8
8
|
*
|
|
9
9
|
* ## 判官
|
|
10
|
-
* 问题:**这把 gate token 是不是该会话当前待决的审批门?**(
|
|
10
|
+
* 问题:**这把 gate token 是不是该会话当前待决的审批门?**(续跑腿的答法:`resumeCheckpoint` 的 stale 臂 —— 回显的 token ≠ 该会话当前待决的审批门 ⇒ `409 approval_stale`。)
|
|
11
11
|
* · {@link sightsCurrentGate} —— 「决断方回显的**门身份**(token / `checkpointId`)是不是当前门的同一面」的**唯一**比较(`approval_stale` 律,两道决断门一条,见下一节);
|
|
12
12
|
* 本仓每一处拿**决断方 / 读口给的那把**门身份比「是不是当前门」都经它(`/decide` 的 token 回显、计划审阅的身份回显、下面的 {@link readGateCurrency});
|
|
13
13
|
* 服务端对**自己选出的那张卡**的复核不是回显比较,不经它(`drivePlanReview` 的卡令牌复核答认领输家 `409 conflict.not_resumable`、唤醒腿的赢家比较);
|
|
14
14
|
* 射程:本判官问的是「**哪扇门**」;`/decide` 的 [ref] 第二源问的是「**哪只调用**」(回显的 `boundCallId` vs 载入行的 `toolCallId`)—— 两问不同,所以是两条比较,
|
|
15
15
|
* 不是「不能并」:它们共用同一个 409 答复,缺值规则各按各的问题定(说不出门身份 ⇒ 判「不是」;行上没有 `toolCallId` ⇒ 那一问不判,交引擎的绑定等值校验 fail-closed 兜)。
|
|
16
16
|
* 过期决断的 409 一族(门身份 / 调用绑定两问怎么排成一族、老行那一形答哪个码)是 7.138.0 的设计票(DEBTS-server,主会话开票);
|
|
17
|
-
* · {@link currentApprovalGateToken} —— 该会话当前待决的审批门(审批门型优先,没有再退到任一待决行)
|
|
17
|
+
* · {@link currentApprovalGateToken} —— 该会话当前待决的审批门(审批门型优先,没有再退到任一待决行);续跑腿的 stale 臂读它,读口读它,别处不再内联第二份;
|
|
18
18
|
* · {@link readGateCurrency} —— 一把 token 对着它的读数:`current`(带那一行)/ `absent`(店里没有这一行)/ `settled`(行在,但不再是当前待决门:已结算、已过期、被取代);
|
|
19
19
|
* · {@link createParkedGateRead} —— 协调器读口的门读席:把读数译成读口要的四种读法({@link ParkedGateReading}),`state` 闭集不加字。
|
|
20
20
|
*
|
|
@@ -46,19 +46,19 @@
|
|
|
46
46
|
* ## `settled` 怎么译(读口只说 checkpoint 上有凭据的话;一条规矩)
|
|
47
47
|
* 落盘的行不受类型面约束(旧版 / 手改 / 坏体 / 更新版本 core 写下的行可带闭集外的词或坏形),所以已结算门只按**一条规矩**读:
|
|
48
48
|
* ① 两个闭集词(行的 `status`、结算记录的种类 `settlement.kind`)各查一张穷举表,**同一查法**({@link throughTable}:只认表自己的键,非字符串不进表):
|
|
49
|
-
* 表明说 `decided` ⇒ 往下读;明说 `void` ⇒ `void`(没有人决过它,答案无处兑现 —— 已过期〔取消 /
|
|
49
|
+
* 表明说 `decided` ⇒ 往下读;明说 `void` ⇒ `void`(没有人决过它,答案无处兑现 —— 已过期〔取消 / 收割〕、仍待决却不是当前门〔被取代,决断口的停驻形答 `approval_stale`〕、
|
|
50
50
|
* 结算种类是引擎窗到期 / 宿主 SLA 扫 / 无人可答的失败族);**表外 ⇒ `unknown`**(读不懂的词撑不起「有人决过」,也撑不起「没有人决过它」);
|
|
51
51
|
* ② 结算赢家的门记录 `resolvedOutcome.gateOutcome` 先过 core 唯一的门记录筛 `screenGateOutcome`(**档案读法**:读回的耐久行,闭集 = 今日成员 ∪ 已退役词;
|
|
52
52
|
* 坏形记缺陷、绝不抛;本仓 `trace/project.ts` 投影同一种记录也只经这一只筛),有缺陷 ⇒ `unknown`,过了筛才读它的成员。core 7.56.0 [ref] 起筛自己判
|
|
53
53
|
* I10(`settlement.when` 是有限数)与 I11(调用方把赢家的 `decision` 一并交给筛:它是赢家拿得出的词,方向与记录的结算种类 / 处置同向)—— 本判官在同一次筛调用里
|
|
54
54
|
* 交 `winnerDecision`,时刻与方向的手判随之退役;
|
|
55
55
|
* ③ 分类之前记录要**读得全**:有结算记录、赢家绑的是这一行的调用且判词是 allow / deny(与
|
|
56
|
-
* `findDecidedApprovalsForBinding` 同一只 {@link approvalDecisionOfWinner})—— 缺一个都是 `unknown`(**不编一个首决**;读口答 404
|
|
56
|
+
* `findDecidedApprovalsForBinding` 同一只 {@link approvalDecisionOfWinner})—— 缺一个都是 `unknown`(**不编一个首决**;读口答 404,决断口的停驻臂读作门上没站着决定;
|
|
57
57
|
* `void` 也要读得全:绑在别的调用上的结算说的不是这张卡);读全了再按**结算种类**表分类:人 / 策略的四个种类 ⇒ `decided`(理由取自赢家的 `reason`),其余十个 ⇒ `void`
|
|
58
58
|
* (按种类不按当事方:跨版本稳定的是种类词,变过义的是当事方词 —— 此前版本的策略拒记 `policy_refused` + `who.party:"none"`,此后记 `"policy"`,按当事方查会把那一代合法历史记录读成 `void`);
|
|
59
59
|
* ④ 读的只是行的内容、不碰店:内容坏到读的时候抛(行上缺了必填成员)同样是坏行 ⇒ `unknown`,不冒成店故障(读口对店故障退回 `parked`)。
|
|
60
60
|
* `unknown` 的这一类(`decision_unreadable`)带上读不出的那几处(缺陷句,非空):读口答 404 `tool_approval.not_pending`,并记一行 error(首句 + 计数)。
|
|
61
|
-
* 行没了 ⇒ `unknown`(`row_absent
|
|
61
|
+
* 行没了 ⇒ `unknown`(`row_absent`;赎回席对「checkpoint 行没了」的 404 `not_found.approval`〔决断口渲成 `not_found.ask`〕同判)。
|
|
62
62
|
*
|
|
63
63
|
* ## 盲区(core 的筛仍不判的一处,如实写下)
|
|
64
64
|
* · 种类 × 当事方的配对(结算种类与 `settlement.who` 的当事方是否相配)—— 筛不判(core [ref]),本判官也不核:读的是种类。只有坏行 / 手改行才走得到。
|
|
@@ -99,7 +99,7 @@ export interface GateCurrencyStore {
|
|
|
99
99
|
}
|
|
100
100
|
/**
|
|
101
101
|
* 该会话**当前待决的审批门**的 token:审批门型({@link APPROVAL_GATE_KINDS})优先 —— 同会话 `task_done` 纯 park 与新 run 的审批 park 可以并存(表无 per-session pending 唯一约束),
|
|
102
|
-
* 无序读会选中别的门型 —— 没有审批门才退到任一待决行(错门型诊断由 `/decide` 的 gate-kind 守卫点名)
|
|
102
|
+
* 无序读会选中别的门型 —— 没有审批门才退到任一待决行(错门型诊断由 `/decide` 的 gate-kind 守卫点名)。续跑腿的 stale 臂与按问读口读这一只。
|
|
103
103
|
*/
|
|
104
104
|
export declare function currentApprovalGateToken(cs: Pick<GateCurrencyStore, "findPendingTokenBySession">, sessionId: string): Promise<CheckpointToken | null | undefined>;
|
|
105
105
|
/** 一把 gate token 对着判官的读数(`current` / `settled` 带分类用的那一行)。 */
|
|
@@ -91,21 +91,20 @@ function readWinner(checkpoint, gateBoundCallId) {
|
|
|
91
91
|
if (byKind !== "decided")
|
|
92
92
|
return byKind;
|
|
93
93
|
const note = typeof winner?.reason === "string" && winner.reason !== "" ? winner.reason : undefined;
|
|
94
|
-
return { kind: "decided", decision: direction
|
|
94
|
+
return { kind: "decided", decision: direction, decidedAtMs: settlement.when, ...(note !== undefined ? { decisionNote: note } : {}) };
|
|
95
95
|
}
|
|
96
96
|
function isReopenReason(word) {
|
|
97
97
|
return typeof word === "string" && REOPEN_REASONS.includes(word);
|
|
98
98
|
}
|
|
99
99
|
function openReading(checkpoint, gateBoundCallId) {
|
|
100
|
-
const generation = checkpointRevOf(checkpoint);
|
|
101
100
|
const reason = checkpoint.reopenReason;
|
|
102
101
|
if (!isReopenReason(reason))
|
|
103
|
-
return { kind: "open"
|
|
102
|
+
return { kind: "open" };
|
|
104
103
|
const prior = decisionReading(checkpoint, gateBoundCallId);
|
|
105
104
|
const reopened = prior.kind === "decided"
|
|
106
105
|
? { reason, decision: prior.decision, decidedAtMs: prior.decidedAtMs, ...(prior.decisionNote !== undefined ? { decisionNote: prior.decisionNote } : {}) }
|
|
107
106
|
: { reason };
|
|
108
|
-
return { kind: "open",
|
|
107
|
+
return { kind: "open", reopened };
|
|
109
108
|
}
|
|
110
109
|
export function createParkedGateRead(cs) {
|
|
111
110
|
return async ({ gateToken, gateBoundCallId }) => {
|
package/dist/approval-hmac.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ParsedPersistRule } from "./tool-approval.js";
|
|
1
2
|
import type { QuestionAnswer } from "@sema-agent/core";
|
|
2
3
|
import type { ApprovalHmacKey } from "./auth-keys.js";
|
|
3
4
|
/**
|
|
@@ -76,6 +77,15 @@ export declare function projectQuestionAnswer(a: QuestionAnswer): QuestionAnswer
|
|
|
76
77
|
* 而是先投影(签它)、再由本函数重建(送它)—— 中间没有第二条路径,所以「签了 A 却转发了 A′」
|
|
77
78
|
* 在结构上不可能。`note` 为 `null` ⇒ **不造键**(与 core `QuestionAnswerItem.note?` 的缺席同义)。 */
|
|
78
79
|
export declare function questionAnswerFromProjection(p: QuestionAnswerProjection): QuestionAnswer;
|
|
80
|
+
/**
|
|
81
|
+
* 「不再询问」规则位(`/decide` 体上的 `persistRule`,已过唯一体形判官)在签名载荷里的**投影**:一只定序元组 —— batch 臂 `["batch", 下标]`,文本两臂
|
|
82
|
+
* `["text", 规则文本, edited]`。签的是投影、转发的是由同一份投影重建的那一位({@link persistRuleFromProjection}),「签了 A 却兑了 A′」结构上不可能(与 `answer` 同形)。
|
|
83
|
+
* 不送它的签名器零改动(扩展位,缺席 ⇒ 一个字节都不追加)。
|
|
84
|
+
*/
|
|
85
|
+
export type PersistRuleProjection = readonly ["batch", number] | readonly ["text", string, boolean];
|
|
86
|
+
export declare function projectPersistRule(slot: ParsedPersistRule): PersistRuleProjection;
|
|
87
|
+
/** 投影 → 兑付收的那一位(**「签的 = 兑的」的兑现点**)。 */
|
|
88
|
+
export declare function persistRuleFromProjection(p: PersistRuleProjection): ParsedPersistRule;
|
|
79
89
|
/**
|
|
80
90
|
* 信封的**扩展键闭集**(字典序 = 声明序 = `ext` 的 JSON 键序)。
|
|
81
91
|
*
|
|
@@ -83,7 +93,7 @@ export declare function questionAnswerFromProjection(p: QuestionAnswerProjection
|
|
|
83
93
|
* 下面那两条编译期门当场红。**不许有第三种在场判**:恒 `!== undefined`(不是真值判、也不是 `?? null`
|
|
84
94
|
* 折叠)—— `null` 与缺席在扩展位上是两个不同的被签值(「签名方明说这次不动」≠「签名方不知道有这个键」)。
|
|
85
95
|
*/
|
|
86
|
-
export declare const APPROVAL_ENVELOPE_EXT_KEYS: readonly ["answer", "checkpointId", "permissionModeAfter"];
|
|
96
|
+
export declare const APPROVAL_ENVELOPE_EXT_KEYS: readonly ["answer", "checkpointId", "permissionModeAfter", "persistRule"];
|
|
87
97
|
export type ApprovalEnvelopeExtKey = (typeof APPROVAL_ENVELOPE_EXT_KEYS)[number];
|
|
88
98
|
/** The canonical envelope both {@link approvalHmacMessage} (the signer's/verifier's shared byte-rule) and
|
|
89
99
|
* {@link verifyApprovalHmac} take — ONE named type so the two signatures cannot silently drift into two
|
|
@@ -128,6 +138,12 @@ export interface ApprovalEnvelope {
|
|
|
128
138
|
* —— 证明是瞬时物不是持久数据,没有迁移面,消费方的 401 就是通知(宪法「hard breaking 三句」)。
|
|
129
139
|
*/
|
|
130
140
|
permissionModeAfter?: string | null;
|
|
141
|
+
/**
|
|
142
|
+
* `/decide` 的「不再询问」规则位(投影形 {@link PersistRuleProjection})进签名载荷。一条规则就是一条常驻放行 —— 与 `answer` / `permissionModeAfter` 同一条判据:
|
|
143
|
+
* **凡改变续跑能做什么 / 落什么账的决裁字段都在签名信封里**。直连门部署上停驻卡只有 `/decide` 这一扇口,拒收它就在这里造出一处「行说有、门拒键」。
|
|
144
|
+
* 在场才进扩展对象;缺席 ⇒ 字节与不认识它的签名器逐字相同(既有签名器零改动);带了不签 ⇒ `401 approval_mac_invalid`。
|
|
145
|
+
*/
|
|
146
|
+
persistRule?: PersistRuleProjection;
|
|
131
147
|
}
|
|
132
148
|
export declare function approvalHmacMessage(env: ApprovalEnvelope): string;
|
|
133
149
|
/** 签名载荷里 `reason` 的字符上限。**拒**而不是截 —— 截断在这条路径上**结构上不可行**:服务端截过的字节
|
package/dist/approval-hmac.js
CHANGED
|
@@ -5,7 +5,13 @@ export function projectQuestionAnswer(a) {
|
|
|
5
5
|
export function questionAnswerFromProjection(p) {
|
|
6
6
|
return { answers: p.map(([header, selected, note]) => ({ header, selected: [...selected], ...(note === null ? {} : { note }) })) };
|
|
7
7
|
}
|
|
8
|
-
export
|
|
8
|
+
export function projectPersistRule(slot) {
|
|
9
|
+
return slot.kind === "batch" ? ["batch", slot.batchOfferIndex] : ["text", slot.rule, slot.edited];
|
|
10
|
+
}
|
|
11
|
+
export function persistRuleFromProjection(p) {
|
|
12
|
+
return p[0] === "batch" ? { kind: "batch", batchOfferIndex: p[1] } : { kind: "text", rule: p[1], edited: p[2] };
|
|
13
|
+
}
|
|
14
|
+
export const APPROVAL_ENVELOPE_EXT_KEYS = ["answer", "checkpointId", "permissionModeAfter", "persistRule"];
|
|
9
15
|
const APPROVAL_ENVELOPE_HEAD_KEYS = ["sessionId", "boundCallId", "boundInputHash", "decision", "reason"];
|
|
10
16
|
export function approvalHmacMessage(env) {
|
|
11
17
|
const head = [env.sessionId, env.boundCallId ?? null, env.boundInputHash ?? null, env.decision, env.reason ?? null];
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* ## 规则(一句)
|
|
5
5
|
* `GET /v1/approvals` 的 `pending[]`(与 `/v1/approvals/stream` 的 `pending` / `resolved` 帧)= **决断口是 `POST /v1/approvals/:id/decide` 的全部行**;
|
|
6
6
|
* 每一行自报它属于哪一族(`kind`,本闭集一词),消费方**先按 `kind` 分支**,再读那一族的键。数组名仍是决断口的判据(`livePending[]` 的口是
|
|
7
|
-
* `POST /v1/
|
|
7
|
+
* 决断口 `POST /v1/tasks/:taskId/asks/:askId/decision`,不在本闭集里);本闭集回答的是「同一扇门后面是哪一种卡」。
|
|
8
8
|
*
|
|
9
9
|
* · `checkpoint` —— 停驻门(durable park):行 = 店的 `listPending` 那一行(键集照旧,另带 `kind`),门的 `:id` = 行的 `sessionId`,
|
|
10
10
|
* 再按 `gateKind`(core 的门型闭集)分路;
|
package/dist/approval.d.ts
CHANGED
|
@@ -71,8 +71,8 @@ export declare function gateIntentUnserviceableReason(config: GateIntentView, ch
|
|
|
71
71
|
/**
|
|
72
72
|
* [ref] C3 —— 「**无应答面**」两条 boot warn 的判据与文案(纯函数;stage-07 只负责打日志)。
|
|
73
73
|
*
|
|
74
|
-
* 两条 warn 警的是同一类失败:一个 `ask` 发生了,而这台部署既没有活体协调器(
|
|
75
|
-
* durable 停车(`DURABLE_APPROVAL`)⇒ core `resolveAsk` 无 onAsk ⇒ headless 自动拒(fail-closed,写进转录)。
|
|
74
|
+
* 两条 warn 警的是同一类失败:一个 `ask` 发生了,而这台部署既没有活体协调器(只在呈卡协议上场时构造:`TOOL_APPROVAL_ENABLED` ∧ store backend ∧
|
|
75
|
+
* park 设施)也没有 durable 停车(`DURABLE_APPROVAL`)⇒ core `resolveAsk` 无 onAsk ⇒ headless 自动拒(fail-closed,写进转录)。
|
|
76
76
|
* 运维要在 **boot** 就知道,否则会把随之而来的拒绝读成故障。两条 warn 按「ask 从哪来」**划分车道**,互补不重叠:
|
|
77
77
|
* · `fs_write_gate_no_responder` —— 写门的 Write/Edit ask。它只在**手写本机盘**时才会发生(写门挂在 host
|
|
78
78
|
* 语义上,而 ask 要有手去触发)⇒ 判据 = {@link handsOnWorkerFilePlane}(今天 = `host`)。改前写的是
|
package/dist/approval.js
CHANGED
|
@@ -39,7 +39,7 @@ export function buildNoResponderBootWarns(input) {
|
|
|
39
39
|
out.push({
|
|
40
40
|
event: "fs_write_gate_no_responder",
|
|
41
41
|
fields: {
|
|
42
|
-
hint: "host-semantics lane with no approval face: the engine's write-gate asks (permissionMode default/auto, absent reads as default; acceptEdits outside the write roots) will auto-deny (fail-closed); wire
|
|
42
|
+
hint: "host-semantics lane with no approval face: the engine's write-gate asks (permissionMode default/auto, absent reads as default; acceptEdits outside the write roots) will auto-deny (fail-closed); wire DURABLE_APPROVAL=true on a store backend (DB_BACKEND) to answer them (approval cards additionally need TOOL_APPROVAL_ENABLED)",
|
|
43
43
|
},
|
|
44
44
|
});
|
|
45
45
|
}
|
|
@@ -47,7 +47,7 @@ export function buildNoResponderBootWarns(input) {
|
|
|
47
47
|
out.push({
|
|
48
48
|
event: "workflow_gate_no_responder",
|
|
49
49
|
fields: {
|
|
50
|
-
hint: "self-orchestration with no approval face: run_workflow asks (every permission mode but bypassPermissions, which releases them, and dontAsk, which refuses them; absent reads as default) will auto-deny (fail-closed); wire
|
|
50
|
+
hint: "self-orchestration with no approval face: run_workflow asks (every permission mode but bypassPermissions, which releases them, and dontAsk, which refuses them; absent reads as default) will auto-deny (fail-closed); wire DURABLE_APPROVAL=true on a store backend (DB_BACKEND) to answer them (approval cards additionally need TOOL_APPROVAL_ENABLED)",
|
|
51
51
|
},
|
|
52
52
|
});
|
|
53
53
|
}
|
package/dist/bind-host.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
/** 读监听地址要的那几格(取自配置的同名键)。 */
|
|
2
2
|
export interface BindHostConfig {
|
|
3
3
|
bindHost?: string;
|
|
4
|
-
/** 缝合审 M5:`bindHost` 的**来源**决定它算不算 operator 明示,见 {@link resolveBindHost}。 */
|
|
5
|
-
bindHostSource?: "BIND_HOST" | "HOST";
|
|
6
4
|
allowUnauthedWrites?: boolean;
|
|
7
5
|
authToken?: string;
|
|
8
6
|
authTokens?: Record<string, string>;
|
|
@@ -12,7 +10,7 @@ export interface BindHostConfig {
|
|
|
12
10
|
export declare function bindMustNarrow(config: Pick<BindHostConfig, "allowUnauthedWrites" | "authToken" | "authTokens">): boolean;
|
|
13
11
|
/**
|
|
14
12
|
* 这台进程的监听地址(绑址旋钮 + 无鉴权自收窄)。`undefined` = Node 缺省全接口。
|
|
15
|
-
* `BIND_HOST`(
|
|
13
|
+
* `BIND_HOST` 显式值恒生效(绑址的唯一来源:`HOST` 不读);缺省:**无鉴权写面(`allowUnauthedWrites` 且零凭据)自动收窄到 127.0.0.1**,其余维持全接口。
|
|
16
14
|
*/
|
|
17
15
|
export declare function resolveBindHost(config: BindHostConfig): string | undefined;
|
|
18
16
|
/**
|
package/dist/bind-host.js
CHANGED
|
@@ -5,10 +5,9 @@ export function bindMustNarrow(config) {
|
|
|
5
5
|
return Boolean(config.allowUnauthedWrites) && !hasServiceAuth(config);
|
|
6
6
|
}
|
|
7
7
|
export function resolveBindHost(config) {
|
|
8
|
-
|
|
9
|
-
if (config.bindHost && !(mustNarrow && config.bindHostSource === "HOST"))
|
|
8
|
+
if (config.bindHost)
|
|
10
9
|
return config.bindHost;
|
|
11
|
-
return
|
|
10
|
+
return bindMustNarrow(config) ? "127.0.0.1" : undefined;
|
|
12
11
|
}
|
|
13
12
|
export function listensLoopbackOnly(bindHost) {
|
|
14
13
|
if (bindHost === undefined)
|
|
@@ -38,7 +38,7 @@ export interface LiveCoordinatorsCtx {
|
|
|
38
38
|
* 提交了没有」—— 审计 settle 行等 park 提交落定才写。缺席 = 没有 park 设施(core 在 ask 回调处就收场,没有提交这一步)。 */
|
|
39
39
|
parkCommits?: ParkCommitWatch;
|
|
40
40
|
/** [ref]:checkpoint 店(stage-06 的**同一只**,与 `parkCommits` 同源;在场 ⇔ 有 park 设施)。协调器的按问读口据它判一张 `PARKED` 卡的门此刻还是不是该会话当前待决的审批门
|
|
41
|
-
* (判官 = `approval-gate-currency.ts
|
|
41
|
+
* (判官 = `approval-gate-currency.ts`,续跑腿判 `approval_stale` 读的同一只)。缺席 ⇒ 读口只能说行说的话(`parked`)。
|
|
42
42
|
* 也是流内审批协议上场门的 park 设施位:在场性与实例是一个事实 —— 门的 `active` 臂交出去的就是这一只,缺席 ⇒ 协议不上场(`no_park_facility`)。 */
|
|
43
43
|
checkpointStore?: GateCurrencyStore;
|
|
44
44
|
}
|
|
@@ -19,18 +19,18 @@ export function createLiveCoordinators(ctx) {
|
|
|
19
19
|
const durableEnabled = parkStore !== undefined;
|
|
20
20
|
const streamApprovalGate = resolveStreamApprovalGate({
|
|
21
21
|
toolApprovalEnabled: config.toolApprovalEnabled === true,
|
|
22
|
-
streamApprovalEnabled: config.streamApproval.enabled,
|
|
23
22
|
backend,
|
|
24
23
|
checkpointStore: parkStore,
|
|
25
24
|
});
|
|
26
|
-
if (
|
|
27
|
-
logger.
|
|
25
|
+
if (!streamApprovalGate.active && streamApprovalGate.reason !== "no_tool_approval") {
|
|
26
|
+
logger.warn("approval_cards_unavailable", {
|
|
28
27
|
reason: streamApprovalGate.reason,
|
|
29
28
|
backendKind: backend?.kind ?? null,
|
|
30
29
|
checkpointStore: backend?.checkpoint !== undefined,
|
|
31
30
|
durableApproval: config.durableApproval === true,
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
unattendedPolicy: config.unattendedApprovalPolicy,
|
|
32
|
+
note: "no approval card is presented on ANY leg of this worker (approval cards need a durable approval ledger: a store backend plus a park facility), so every gated tool call is refused fail-closed. " +
|
|
33
|
+
"Set DURABLE_APPROVAL=true on a store backend (DB_BACKEND) to get approval cards.",
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
36
|
if (config.toolApprovalEnabled === true && config.streamApproval.windowMs === 0) {
|
|
@@ -47,12 +47,11 @@ export function createLiveCoordinators(ctx) {
|
|
|
47
47
|
? new FileApprovalAskAuditStore(config.localDataRoot)
|
|
48
48
|
: undefined;
|
|
49
49
|
const approvalExemptionStore = backend ? backend.approvalExemption() : undefined;
|
|
50
|
-
const toolApproval =
|
|
50
|
+
const toolApproval = streamApprovalGate.active
|
|
51
51
|
? new ToolApprovalCoordinator({
|
|
52
52
|
ttlMs: config.streamApproval.windowMs,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
: {}),
|
|
53
|
+
askStore: streamApprovalGate.askStore,
|
|
54
|
+
unreachedTtlMs: config.streamApproval.unreachedTtlMs,
|
|
56
55
|
windowMarginMs: config.streamAskWindowMarginMs,
|
|
57
56
|
admitMaxPerTask: config.streamApproval.admitMaxPerTask,
|
|
58
57
|
admitMaxPerOwner: config.streamApproval.admitMaxPerOwner,
|
|
@@ -103,7 +102,7 @@ export function createLiveCoordinators(ctx) {
|
|
|
103
102
|
const send = sendFileLedger
|
|
104
103
|
? withLedgerRecording(rawSend, {
|
|
105
104
|
ledger: sendFileLedger,
|
|
106
|
-
deleteObject: (bucket, key) => issuer.deleteObject(bucket, key),
|
|
105
|
+
deleteObject: (bucket, key, track) => issuer.deleteObject(bucket, key, track),
|
|
107
106
|
warn: (msg, meta) => logger.warn(msg, meta),
|
|
108
107
|
})
|
|
109
108
|
: rawSend;
|