@sema-agent/server 7.135.0 → 7.137.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATION.md +237 -2
- package/USAGE.md +146 -41
- package/deploy/sema-up/README.md +15 -1
- package/deploy/sema-up/chart/templates/NOTES.txt +1 -1
- package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +7 -1
- package/deploy/sema-up/chart/values.yaml +1 -1
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +7 -1
- package/dist/approval-card.d.ts +60 -4
- package/dist/approval-card.js +18 -1
- package/dist/approval-content-kind.d.ts +7 -0
- package/dist/approval-content-kind.js +8 -1
- package/dist/approval-gate-currency.d.ts +48 -6
- package/dist/approval-gate-currency.js +16 -9
- package/dist/approval-hmac.d.ts +13 -1
- package/dist/approval-hmac.js +1 -1
- package/dist/approval.js +3 -3
- package/dist/auth-bridge.d.ts +34 -5
- package/dist/auth-bridge.js +22 -5
- package/dist/boot/budget-tracing.d.ts +1 -2
- package/dist/boot/budget-tracing.js +2 -2
- package/dist/boot/execution-env.d.ts +24 -1
- package/dist/boot/execution-env.js +69 -6
- package/dist/boot/org-memory.js +1 -1
- package/dist/boot/reapers.d.ts +3 -0
- package/dist/boot/reapers.js +15 -1
- package/dist/boot/resolve-spec.d.ts +4 -0
- package/dist/boot/resolve-spec.js +24 -22
- package/dist/boot/runner-deps.js +4 -2
- package/dist/boot/stage-03-store-backend.d.ts +1 -1
- package/dist/boot/stage-04-stores.d.ts +2 -2
- package/dist/boot/stage-05-execution-env.d.ts +4 -2
- package/dist/boot/stage-05-execution-env.js +11 -2
- package/dist/boot/stage-06-runners.d.ts +4 -2
- package/dist/boot/stage-06-runners.js +5 -1
- package/dist/boot/stage-07-capability-layer.d.ts +5 -2
- package/dist/boot/stage-07-capability-layer.js +1 -1
- package/dist/boot/stage-08-reapers.d.ts +5 -2
- package/dist/boot/stage-08-reapers.js +2 -1
- package/dist/boot/stage-09-leader.d.ts +5 -2
- package/dist/boot/stage-10-http-server.d.ts +5 -2
- package/dist/boot/stage-10-http-server.js +3 -2
- package/dist/boot/stores.d.ts +1 -1
- package/dist/boot/stores.js +2 -3
- package/dist/boot/web-admin.js +10 -17
- package/dist/brain.js +12 -3
- package/dist/broker/broker.d.ts +89 -0
- package/dist/broker/broker.js +287 -0
- package/dist/broker/constants.d.ts +39 -0
- package/dist/broker/constants.js +15 -0
- package/dist/broker/http1.d.ts +111 -0
- package/dist/broker/http1.js +256 -0
- package/dist/broker/lease-book.d.ts +87 -0
- package/dist/broker/lease-book.js +142 -0
- package/dist/broker/lease-file.d.ts +60 -0
- package/dist/broker/lease-file.js +127 -0
- package/dist/broker/main.d.ts +2 -0
- package/dist/broker/main.js +20 -0
- package/dist/budget.d.ts +3 -3
- package/dist/budget.js +4 -0
- package/dist/capabilities/composite-members.d.ts +2 -1
- package/dist/capabilities/composite-members.js +2 -1
- package/dist/capabilities/engine-capabilities.js +1 -0
- package/dist/capabilities/mcp-probe.d.ts +5 -4
- package/dist/capabilities/scenarios.d.ts +23 -8
- package/dist/capabilities/scenarios.js +13 -8
- package/dist/capabilities/skills.d.ts +28 -5
- package/dist/capabilities/skills.js +8 -0
- package/dist/capability-facts.d.ts +3 -7
- package/dist/capability-facts.js +3 -5
- package/dist/center-credential-renewer.js +5 -1
- package/dist/center-credential.d.ts +18 -4
- package/dist/center-credential.js +18 -3
- package/dist/checkpoint-ctx-seal-m28.d.ts +3 -10
- package/dist/checkpoint-ctx-seal-m28.js +1 -1
- package/dist/checkpoint-identity.d.ts +3 -3
- package/dist/config-catalog.js +21 -16
- package/dist/config-d-migration.js +1 -1
- package/dist/config-invariants.d.ts +1 -1
- package/dist/config-invariants.js +8 -0
- package/dist/config-lkg.d.ts +0 -38
- package/dist/config-lkg.js +1 -83
- package/dist/config-types.d.ts +21 -4
- package/dist/config.d.ts +1 -1
- package/dist/config.js +60 -16
- package/dist/deployment-governance.d.ts +2 -2
- package/dist/deployment-governance.js +7 -9
- package/dist/deployment-shape.d.ts +1 -1
- package/dist/device-ws-protocol.d.ts +1 -0
- package/dist/device-ws-protocol.js +2 -1
- package/dist/elicitation.d.ts +8 -7
- package/dist/elicitation.js +9 -8
- package/dist/file-history-disclosure.d.ts +8 -4
- package/dist/file-history-disclosure.js +24 -6
- package/dist/fleet-client.d.ts +32 -1
- package/dist/fleet-client.js +24 -4
- package/dist/fleet-lease.d.ts +7 -3
- package/dist/fleet-lease.js +31 -23
- package/dist/hooks/classic-stations.d.ts +11 -54
- package/dist/hooks/hook-llm.js +14 -8
- package/dist/hooks/hook-runner.d.ts +4 -4
- package/dist/hooks/hook-runner.js +2 -2
- package/dist/http/admission.js +10 -7
- package/dist/http/approval-sweeps.js +4 -3
- package/dist/http/caller-trust.d.ts +2 -1
- package/dist/http/caller-trust.js +1 -3
- package/dist/http/checkpoint-ctx.d.ts +76 -16
- package/dist/http/checkpoint-ctx.js +45 -1
- package/dist/http/dispatch.js +24 -19
- package/dist/http/durable-run-leg.d.ts +5 -1
- package/dist/http/durable-run-leg.js +1 -1
- package/dist/http/health-self-report.d.ts +2 -2
- package/dist/http/mcp-remote-text.d.ts +5 -0
- package/dist/http/mcp-remote-text.js +7 -0
- package/dist/http/principal-gate.d.ts +15 -10
- package/dist/http/principal-gate.js +48 -9
- package/dist/http/resume-ctx-read.d.ts +2 -16
- package/dist/http/resume-ctx-read.js +2 -3
- package/dist/http/resume-legs.d.ts +2 -20
- package/dist/http/resume-legs.js +52 -38
- package/dist/http/route-ctx.d.ts +8 -2
- package/dist/http/routes/approvals-assistant.d.ts +0 -2
- package/dist/http/routes/approvals-assistant.js +65 -16
- package/dist/http/routes/capabilities.js +11 -1
- package/dist/http/routes/mcp-reconnect.d.ts +1 -1
- package/dist/http/routes/mcp-reconnect.js +5 -7
- package/dist/http/routes/runs.js +4 -3
- package/dist/http/routes/session-sync.js +70 -12
- package/dist/http/routes/sessions.js +20 -15
- package/dist/http/routes/tasks.js +8 -6
- package/dist/http/server.d.ts +4 -0
- package/dist/http/stored-body-replay.d.ts +3 -3
- package/dist/http/stored-body-replay.js +6 -1
- package/dist/http/submit-ctx.js +1 -1
- package/dist/http/wire-types.d.ts +57 -30
- package/dist/identity-source.d.ts +65 -0
- package/dist/identity-source.js +45 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/memory-store-refusal.d.ts +3 -3
- package/dist/model-entry-refusal.d.ts +2 -0
- package/dist/model-entry-refusal.js +11 -0
- package/dist/model-route-gap.d.ts +49 -4
- package/dist/model-route-gap.js +34 -1
- package/dist/model-select.d.ts +6 -17
- package/dist/model-select.js +0 -3
- package/dist/namespaced-rule-name.d.ts +1 -1
- package/dist/object-store-buckets.d.ts +13 -0
- package/dist/object-store-buckets.js +3 -0
- package/dist/observability/fail-open.d.ts +19 -7
- package/dist/observability/fail-open.js +19 -7
- package/dist/observability/metrics.js +2 -2
- package/dist/observability/principal-context.d.ts +4 -1
- package/dist/observability/principal-context.js +6 -1
- package/dist/observability/run-terminal.js +1 -0
- package/dist/operator-ask.d.ts +2 -2
- package/dist/org-delivery-gate.js +1 -1
- package/dist/org-memory-admission.d.ts +2 -2
- package/dist/org-memory-admission.js +39 -2
- package/dist/parked-decide.d.ts +4 -3
- package/dist/parked-decide.js +29 -9
- package/dist/peer-directory.d.ts +2 -1
- package/dist/peer-directory.js +7 -5
- package/dist/permission-rule-list.d.ts +2 -2
- package/dist/plugins/approval-ask-store-sql.d.ts +8 -0
- package/dist/plugins/approval-ask-store-sql.js +3 -0
- package/dist/plugins/blob-backend.js +2 -1
- package/dist/plugins/checkpoint-index-columns.d.ts +50 -1
- package/dist/plugins/checkpoint-index-columns.js +28 -0
- package/dist/plugins/checkpoint-store-sql.d.ts +46 -12
- package/dist/plugins/checkpoint-store-sql.js +64 -35
- package/dist/plugins/file-history-store-sql.d.ts +6 -0
- package/dist/plugins/file-history-store-sql.js +37 -37
- package/dist/plugins/file-run-store.js +8 -2
- package/dist/plugins/k8s-exec-protocol.d.ts +69 -13
- package/dist/plugins/k8s-exec-protocol.js +116 -28
- package/dist/plugins/k8s-pod-delete-failure.d.ts +25 -0
- package/dist/plugins/k8s-pod-delete-failure.js +17 -0
- package/dist/plugins/k8s-pod-reaper.d.ts +112 -0
- package/dist/plugins/k8s-pod-reaper.js +122 -0
- package/dist/plugins/local-checkpoint-store.d.ts +3 -6
- package/dist/plugins/local-checkpoint-store.js +7 -6
- package/dist/plugins/memory-run-store.js +2 -0
- package/dist/plugins/one-time-migrations.d.ts +49 -37
- package/dist/plugins/one-time-migrations.js +87 -128
- package/dist/plugins/permission-rule-store-file.js +2 -2
- package/dist/plugins/permission-rule-store-sql.d.ts +17 -17
- package/dist/plugins/permission-rule-store-sql.js +16 -17
- package/dist/plugins/pg-pool.js +4 -0
- package/dist/plugins/pg-session-storage.js +2 -2
- package/dist/plugins/remote-env-adb.d.ts +3 -0
- package/dist/plugins/remote-env-adb.js +1 -0
- package/dist/plugins/remote-env-device.d.ts +3 -0
- package/dist/plugins/remote-env-device.js +4 -0
- package/dist/plugins/remote-env-e2b.d.ts +3 -0
- package/dist/plugins/remote-env-e2b.js +1 -0
- package/dist/plugins/remote-env-file-error.d.ts +8 -1
- package/dist/plugins/remote-env-file-error.js +7 -1
- package/dist/plugins/remote-env-host.d.ts +7 -1
- package/dist/plugins/remote-env-host.js +7 -1
- package/dist/plugins/remote-env-k8s.d.ts +154 -14
- package/dist/plugins/remote-env-k8s.js +300 -21
- package/dist/plugins/remote-env-local-docker.d.ts +3 -0
- package/dist/plugins/remote-env-local-docker.js +1 -0
- package/dist/plugins/remote-env-ssh.d.ts +3 -0
- package/dist/plugins/remote-env-ssh.js +1 -0
- package/dist/plugins/run-store-sql.js +10 -4
- package/dist/plugins/s3-answer.d.ts +15 -0
- package/dist/plugins/s3-answer.js +5 -0
- package/dist/plugins/session-ownership.d.ts +17 -3
- package/dist/plugins/session-ownership.js +19 -5
- package/dist/plugins/snapshot-bucket-presence.d.ts +39 -4
- package/dist/plugins/snapshot-bucket-presence.js +35 -7
- package/dist/plugins/sql-errors.d.ts +60 -0
- package/dist/plugins/sql-errors.js +64 -1
- package/dist/plugins/store-contracts.d.ts +10 -1
- package/dist/plugins/store-fault.d.ts +4 -0
- package/dist/plugins/store-fault.js +10 -0
- package/dist/plugins/tidb-pool.js +8 -1
- package/dist/plugins/tidb-session-store.js +2 -2
- package/dist/plugins/web-search.d.ts +1 -1
- package/dist/plugins/web-search.js +2 -2
- package/dist/request-declaration-refusal.d.ts +94 -0
- package/dist/request-declaration-refusal.js +78 -0
- package/dist/request-image-urls.d.ts +6 -0
- package/dist/request-image-urls.js +27 -0
- package/dist/request-key-closure.d.ts +5 -0
- package/dist/request-key-closure.js +5 -2
- package/dist/request-value-closure.d.ts +31 -2
- package/dist/request-value-closure.js +7 -1
- package/dist/rule-entry-list.d.ts +3 -2
- package/dist/rule-entry-list.js +2 -2
- package/dist/rules-consent.js +7 -4
- package/dist/run-local.d.ts +2 -2
- package/dist/runs.js +2 -1
- package/dist/runtime-caps-resolver.js +1 -1
- package/dist/runtime-governance.d.ts +5 -5
- package/dist/sandbox-git-lease.d.ts +49 -0
- package/dist/sandbox-git-lease.js +60 -0
- package/dist/sandbox-git-plane.d.ts +84 -0
- package/dist/sandbox-git-plane.js +105 -0
- package/dist/sandbox-pkg-source.d.ts +28 -1
- package/dist/sandbox-pkg-source.js +1 -2
- package/dist/sealed-key.d.ts +19 -0
- package/dist/sealed-key.js +47 -4
- package/dist/security.d.ts +16 -4
- package/dist/security.js +8 -3
- package/dist/server-secret-env.d.ts +6 -0
- package/dist/server-secret-env.js +14 -0
- package/dist/session-error-wire.d.ts +14 -6
- package/dist/session-error-wire.js +2 -1
- package/dist/session-incarnation.d.ts +16 -5
- package/dist/session-incarnation.js +7 -4
- package/dist/session-policy-wire.d.ts +1 -1
- package/dist/session-policy-wire.js +2 -2
- package/dist/session-row.d.ts +3 -17
- package/dist/session-row.js +4 -0
- package/dist/session-sync.d.ts +15 -3
- package/dist/session-sync.js +5 -2
- package/dist/spec-fields.d.ts +43 -13
- package/dist/spec-fields.js +33 -12
- package/dist/stored-request-prompt-profile-m30.d.ts +49 -0
- package/dist/stored-request-prompt-profile-m30.js +25 -0
- package/dist/task-a2a.d.ts +52 -81
- package/dist/task-a2a.js +219 -89
- package/dist/task-mcp.d.ts +7 -15
- package/dist/task-mcp.js +16 -51
- package/dist/task-settings.d.ts +2 -2
- package/dist/tool-approval.d.ts +35 -12
- package/dist/tool-approval.js +59 -39
- package/dist/tool-rule-names.d.ts +5 -0
- package/dist/trace/core-keyset-guard.d.ts +5 -5
- package/dist/trace/engine-notice-wire.d.ts +1 -1
- package/dist/trace/engine-notice-wire.js +2 -0
- package/dist/trace/exit-seat.js +37 -13
- package/dist/trace/ledger-sink.d.ts +4 -5
- package/dist/trace/ledger-sink.js +3 -7
- package/dist/trace/project.d.ts +37 -3
- package/dist/trace/project.js +20 -6
- package/dist/trace/redact.d.ts +40 -12
- package/dist/trace/redact.js +332 -128
- package/dist/trace/self-minted-wire.d.ts +641 -0
- package/dist/trace/self-minted-wire.js +201 -0
- package/dist/trace/wire-projection-faces.d.ts +5 -3
- package/dist/trace/wire-projection-faces.js +7 -3
- package/dist/url-credential-refusal.d.ts +52 -0
- package/dist/url-credential-refusal.js +14 -0
- package/dist/url-refusal.d.ts +13 -4
- package/dist/url-refusal.js +8 -2
- package/dist/web-admin-client/apply-effective.js +0 -1
- package/dist/web-admin-client/center-request.d.ts +20 -2
- package/dist/web-admin-client/center-request.js +40 -5
- package/dist/web-admin-client/http-client.js +6 -6
- package/dist/web-admin-client/types.d.ts +5 -5
- package/dist/workspace-space.d.ts +27 -0
- package/dist/workspace-space.js +26 -0
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +11 -5
- package/package.json +4 -3
- package/scripts/drain-check-local.mjs +2 -1
- package/scripts/drain-check.mysql.sql +3 -1
- package/scripts/drain-check.pg.sql +3 -1
- package/skills/schedule.md +1 -1
- package/wire-changes/server@7.104.0.json +134 -0
- package/wire-changes/server@7.105.0.json +53 -0
- package/wire-changes/server@7.106.0.json +475 -0
- package/wire-changes/server@7.107.0.json +64 -0
- package/wire-changes/server@7.108.0.json +153 -0
- package/wire-changes/server@7.109.0.json +46 -0
- package/wire-changes/server@7.110.0.json +90 -0
- package/wire-changes/server@7.111.0.json +86 -0
- package/wire-changes/server@7.112.0.json +60 -0
- package/wire-changes/server@7.113.0.json +26 -0
- package/wire-changes/server@7.114.0.json +26 -0
- package/wire-changes/server@7.115.0.json +97 -0
- package/wire-changes/server@7.116.0.json +218 -0
- package/wire-changes/server@7.116.1.json +26 -0
- package/wire-changes/server@7.117.0.json +65 -0
- package/wire-changes/server@7.118.0.json +129 -0
- package/wire-changes/server@7.119.0.json +65 -0
- package/wire-changes/server@7.120.0.json +89 -0
- package/wire-changes/server@7.121.0.json +219 -0
- package/wire-changes/server@7.122.0.json +54 -0
- package/wire-changes/server@7.123.0.json +26 -0
- package/wire-changes/server@7.124.0.json +336 -0
- package/wire-changes/server@7.124.1.json +26 -0
- package/wire-changes/server@7.125.0.json +111 -0
- package/wire-changes/server@7.126.0.json +285 -0
- package/wire-changes/server@7.127.0.json +77 -0
- package/wire-changes/server@7.127.1.json +26 -0
- package/wire-changes/server@7.127.2.json +53 -0
- package/wire-changes/server@7.128.0.json +26 -0
- package/wire-changes/server@7.129.0.json +106 -0
- package/wire-changes/server@7.129.1.json +26 -0
- package/wire-changes/server@7.130.0.json +26 -0
- package/wire-changes/server@7.131.0.json +118 -0
- package/wire-changes/server@7.132.0.json +226 -0
- package/wire-changes/server@7.133.0.json +1155 -0
- package/wire-changes/server@7.134.0.json +107 -0
- package/wire-changes/server@7.135.0.json +174 -0
- package/wire-changes/server@7.136.0.json +448 -0
- package/wire-changes/server@7.137.0.json +825 -0
- package/dist/url-credential.d.ts +0 -52
- package/dist/url-credential.js +0 -49
|
@@ -31,8 +31,14 @@
|
|
|
31
31
|
* 不受影响:那两种行在新旧两种读法下答同一个词。出路:作为新任务重提(仍停驻的先取消),或在它们收尾之前把 `AUTONOMY` 设成 `read-only`(按段的只读围栏,
|
|
32
32
|
* 与 7.121.x 的 `AUTONOMY=plan` 同一个结局,且没有入口地板 ⇒ 不拒)。删除条件登记在 `plugins/one-time-migrations.ts` 的 M12 行。
|
|
33
33
|
*
|
|
34
|
+
* ## 第四问(7.137.0):体里的退役请求键
|
|
35
|
+
* 请求键退役之后(今天一只:`promptProfile` 换成布尔 `promptLean`,{@link RETIRED_REQUEST_KEYS}),新提交带它在键闭集门 400;存体里的旧键由一次性迁移在起服时原地改写
|
|
36
|
+
* (M30,`stored-request-prompt-profile-m30.ts`,行改写经本模块的 {@link rewriteStoredBodyKeys})。改写不到的残留行(窗内从没起过服的部署;起服扫描之后滚动升级里
|
|
37
|
+
* 旧副本才写下的行)体里仍带旧键 ⇒ 拒({@link retiredRequestKeyRefusal},码同前两只读法拒:`checkpoint.unsupported_version`)。**没有**续跑时按旧键读的第二种读法,
|
|
38
|
+
* 也**没有**「旧键无人读、静默续跑」的臂:旧键还在 = 这份体没被改写过,它当年要的形本版读不出来。
|
|
39
|
+
*
|
|
34
40
|
* ## 一只判据、五个问点(`http/stored-body-replay.ts` 的 `storedBodyReplayRefusal` / 本模块的 {@link storedBodyReplayAnswer})
|
|
35
|
-
*
|
|
41
|
+
* 「这条停驻行的持久化体在本版上能否重放」只有**一个**读法:上面四问合在 `stored-body-replay.ts` 的 `storedBodyReplayRefusal` 一处(前两问的判据在本模块、第三问读请求设置
|
|
36
42
|
* 与治理两个属主 —— 本模块的值依赖要留在 node 内建 / 引擎包根之内,随包排空脚本经编译产物读它),答复合在 {@link storedBodyReplayAnswer} 一处。
|
|
37
43
|
* 问点五个,同调同答:续跑驱动段(`resume-legs.ts` `resolveResumeSpecOrBlocked`,另四条腿的唯一判点)· plan_review 的 prepare 段(读类拒,在 nonce 消费之前)·
|
|
38
44
|
* SLA 拒扫腿的跳过臂(`approval-sweeps.ts`)· 终态 run 的 steer 铸唤醒卡之前(`routes/runs.ts`:铸卡前先证明它赎得回,证不出 ⇒ 不铸、当场同一个拒)·
|
|
@@ -110,6 +116,23 @@ export declare function permissionModeReadingStated(ctx: CheckpointCtx): boolean
|
|
|
110
116
|
* 🔴 形是给冻结门看的:`status: <三位数>, body: refusalBody({ errorCode: "<码>", message: "<整句双引号字面>"`,中间只许有空白。
|
|
111
117
|
*/
|
|
112
118
|
export declare function permissionModeReadingRefusal(): ResumeRefusalAnswer;
|
|
119
|
+
/**
|
|
120
|
+
* 第四问:**退役的请求键**闭集(新提交在键闭集门 400;存体里还带着它 = 这份体是更早的写者写下、一次性迁移没改写到的)。加一个 ⇒ 加一行,
|
|
121
|
+
* {@link retiredRequestKeyRefusal} 的 switch 编译红直到给它一句拒句。今天一只:`promptProfile`(7.137.0 起换成布尔 `promptLean`;存体由 M30 起服改写)。
|
|
122
|
+
*/
|
|
123
|
+
export declare const RETIRED_REQUEST_KEYS: readonly ["promptProfile"];
|
|
124
|
+
export type RetiredRequestKey = (typeof RETIRED_REQUEST_KEYS)[number];
|
|
125
|
+
/** 存体顶层带的第一只退役请求键(闭集序);没有 ⇒ `undefined`。只看自有键(原型上的同名不算)。 */
|
|
126
|
+
export declare function retiredRequestKeyOf(body: unknown): RetiredRequestKey | undefined;
|
|
127
|
+
/**
|
|
128
|
+
* 第四问的拒答复 —— 码与落点同另两只读法拒(`checkpoint.unsupported_version`,409;卡仍 pending 时的 `retriable:true` 由 {@link resumeRefusalWithCard} 追加,本铸点不带)。
|
|
129
|
+
* 句子说键、它换成了什么、为什么不续跑,与两条出路(运维在一次性迁移的窗内重启本服务 ⇒ 起服改写存体、同一请求可再发;否则作为新任务重提,仍停驻的先取消)。不回显值。
|
|
130
|
+
* 🔴 形是给冻结门看的:`status: <三位数>, body: refusalBody({ errorCode: "<码>", message: <整句双引号字面 或 一只模板串>`,中间只许有空白(模板串形冻结的是骨架,`${…}` 折成一个洞)。
|
|
131
|
+
* **窗的日期不手写**:`rewriteWindowEnd` 由调用方交 —— 判据(`stored-body-replay.ts`)按「退役键 → 改写它的迁移」那张表读登记表该行的 `removableAfter`,窗只写在登记表一处;
|
|
132
|
+
* 句子写绝对日期(过了这一天读句子的人一眼看出出路已关,不靠「本版发布日」这种随版漂的说法)。
|
|
133
|
+
* 删法见登记表 M30 的 `removal`(唯一来源)。
|
|
134
|
+
*/
|
|
135
|
+
export declare function retiredRequestKeyRefusal(key: RetiredRequestKey, rewriteWindowEnd: string): ResumeRefusalAnswer;
|
|
113
136
|
/**
|
|
114
137
|
* 本行能否被按当前读法重放:体里 `allow` 在生效而行上的记号不是当前这一个词 ⇒ **不能**(`true` = 拒)。
|
|
115
138
|
* 记号缺席、是旧词(`"statement"`)或认不得(手改 / 将来的写者)⇒ 同样拒:只有当前这个词是「按当前读法写下」的证据。
|
|
@@ -127,7 +150,7 @@ export declare function allowListReadingEraOf(ctx: CheckpointCtx): AllowListRead
|
|
|
127
150
|
export declare function allowListReadingRefusal(era: AllowListReadingEra): ResumeRefusalAnswer;
|
|
128
151
|
/**
|
|
129
152
|
* 一条停驻行的持久化体在本版上**不能**重放时,是哪一条规则拒的(闭集;加一条 ⇒ {@link storedBodyReplayAnswer} 的 switch 编译红)。
|
|
130
|
-
* 答 `checkpoint.unsupported_version`
|
|
153
|
+
* 答 `checkpoint.unsupported_version` 的三臂随带这一行的写者版本(续跑上下文的 `writerVersion`,缺席 = 本版之前写下的行)—— 那一码的两版本键由它铸({@link buildCheckpointVersionKeys})。
|
|
131
154
|
*/
|
|
132
155
|
export type StoredBodyReplayRefusal = {
|
|
133
156
|
readonly kind: "allow_list_reading";
|
|
@@ -141,10 +164,16 @@ export type StoredBodyReplayRefusal = {
|
|
|
141
164
|
readonly stored: PermissionMode | undefined;
|
|
142
165
|
readonly floor: PermissionMode;
|
|
143
166
|
readonly writerVersion?: string;
|
|
167
|
+
} | {
|
|
168
|
+
readonly kind: "retired_request_key";
|
|
169
|
+
readonly key: RetiredRequestKey;
|
|
170
|
+
/** 改写这只退役键的一次性迁移窗的最后一天(UTC 日历日 YYYY-MM-DD)—— 登记表那一行的 `removableAfter`,由判据(`stored-body-replay.ts`)读来:本模块的闭包只许 node 内建 / 引擎包根,读不了登记表,日期只能由调用方交。 */
|
|
171
|
+
readonly rewriteWindowEnd: string;
|
|
172
|
+
readonly writerVersion?: string;
|
|
144
173
|
};
|
|
145
174
|
/**
|
|
146
|
-
* 🔴 **`checkpoint.unsupported_version` 的 409 体上两个版本键 —— 唯一铸法;本码每一个铸点同一条律**(core 原码镜像 = `resume-legs.ts` 的 catch
|
|
147
|
-
* = {@link storedBodyReplayAnswer} 的 allow 读法 /
|
|
175
|
+
* 🔴 **`checkpoint.unsupported_version` 的 409 体上两个版本键 —— 唯一铸法;本码每一个铸点同一条律**(core 原码镜像 = `resume-legs.ts` 的 catch 臂;本服务自铸的三只拒
|
|
176
|
+
* = {@link storedBodyReplayAnswer} 的 allow 读法 / 模式词读法 / 退役请求键三臂):续跑上下文带写者版本 ⇒ `{ writerVersion, readerVersion }`;不带(本版之前写下的行)⇒ `{}`,不编值。
|
|
148
177
|
* 两值相等也照带 —— 那是事实(不是版本问题,出路照码与报文);写者比读者新才是「回到写它的那一版去决」。`readerVersion` 由调用方传本进程的服务版本
|
|
149
178
|
* (本模块零值依赖,不自取)。纯数据。
|
|
150
179
|
*/
|
|
@@ -201,11 +230,12 @@ export declare function storedBodyReplayLogFields(refusal: StoredBodyReplayRefus
|
|
|
201
230
|
layer?: InertToolListEntry["layer"];
|
|
202
231
|
storedMode?: PermissionMode | null;
|
|
203
232
|
floor?: PermissionMode;
|
|
233
|
+
key?: RetiredRequestKey;
|
|
204
234
|
note: string;
|
|
205
235
|
};
|
|
206
236
|
/**
|
|
207
237
|
* `stored-body-replay.ts` `storedBodyReplayRefusal` 的答复:每条规则一只既有铸点(allow 记号 ⇒ {@link allowListReadingRefusal};模式词记号 ⇒ {@link permissionModeReadingRefusal};
|
|
208
|
-
*
|
|
238
|
+
* 退役请求键 ⇒ {@link retiredRequestKeyRefusal};这三只答 `checkpoint.unsupported_version`,体按那一码的键律补两版本键,`readerVersion` = 调用方传的本进程服务版本;工具名清单 ⇒ {@link resumeBlockedByPolicyAnswer},与提交腿的 400
|
|
209
239
|
* (该层的拒码:`request.field_invalid` / `config.agent.unknown_tool` / `config.tool_face_control`)同码同句 —— 体上只有这一个问题时;存量体同时还踩中 `resolveSpec` 更早的拒〔三桶超帽 / 托管姿态〕时,提交侧答更早那条、续跑侧答本句,两边都是拒,指路不同)。
|
|
210
240
|
*
|
|
211
241
|
* 🔴 `cardPending` —— **调用方交出的事实**:这一次拒的时候,有没有一张待批卡仍在等。`retriable:true` 说的恰是「卡仍 pending」,所以它只在卡在时在场(经
|
|
@@ -268,14 +298,17 @@ export interface CheckpointCtxSealing extends CheckpointCtxSealer, CheckpointCtx
|
|
|
268
298
|
}
|
|
269
299
|
/**
|
|
270
300
|
* **凭据位闭集**(提交体里值为凭据的位置)。路径段 `*` = 那一格容器的**每一个成员**:数组的每一项、字典的每一个值(一只走法,不分容器种类 —— 字典成员的点名形
|
|
271
|
-
* `field` 是 `.<键>`,数组是 `[<下标>]`)。`map` = 那一格是串值字典,**每一个值**都是凭据(不分哪一键);`value` =
|
|
272
|
-
* 入表判据(一条)
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
301
|
+
* `field` 是 `.<键>`,数组是 `[<下标>]`)。`map` = 那一格是串值字典,**每一个值**都是凭据(不分哪一键);`value` = 那一格本身是凭据(不论是串、数组还是别的形,整只一个值)。
|
|
302
|
+
* 入表判据(一条):本服务替调用方**原样交出去**的配置值 —— **子进程的启动面**(命令行 `command` / `args` 与交给它的 env)、发往对端的**静态请求头**、
|
|
303
|
+
* 请求自带的**搜索后端钥匙**。值是不是秘密不是本层能判的,所以整格封、不判值形(`--token=…` / `-p …` 拆在两个元素里、shell 形的整行,都不靠认形)。
|
|
304
|
+
* · 子进程两座:MCP stdio 传输(`command` / `args` / `env`)与 command hook 条目(`command` / `args`,插件选项 `plugin.options` 的每一个值就是 hook 子进程环境里的
|
|
305
|
+
* `CLAUDE_PLUGIN_OPTION_<KEY>` —— `hooks/command-spawn.ts` 的 `hookPluginEnv`),外加任务 shell 的 `settings.env`。命令行与 env 同判:壳在投影前把 `${user_config.*}`
|
|
306
|
+
* 替成字面值(执行器不做这一替换),参照实现也把 sensitive 选项照样交进子进程,所以命令行里可以就是密钥。`args` 整只数组封成**一只**封签(不逐元素:逐元素判值形是第二只判官)。
|
|
307
|
+
* · 静态头三座:MCP http 传输、A2A 对端〔引擎型注:「e.g. an auth bearer」〕、http hook 条目(契约包的条目形是 `headers: Record<string, string>`、受理面(`parseHooksConfig`)
|
|
308
|
+
* 只判条数与字数、`interpolateHookEnvVars` 只换 `$NAME` 引用而字面值原样上 wire —— 头值可以就是字面的 `Authorization: Bearer …`)。
|
|
309
|
+
* hooks 的形 = 事件名 → 匹配组数组 → 组的 `hooks` 数组 → 条目;只有 `type:"http"` 的条目有 `headers`、只有 command 条目有 `command` / `args` / `plugin.options`,
|
|
310
|
+
* 别的条目在那一段缺席、走法照常不往下走。**不在本表、各归另一条规则**:值是 URL 的字段 —— 带凭据的 URL 在受理口就拒(凭据只许走头位;判官 = 契约包根的 `findUrlCredential`),
|
|
311
|
+
* 所以落盘的 URL 结构上不带凭据;交给模型的文本(目标 / 提示词 / 系统提示)—— 模型看得见的东西本来就进会话记录,封停驻档护不住它。
|
|
279
312
|
* 加一位 = 加一行,读写两侧与一次性迁移 M28 共用 {@link mapCredentialSlots} 一只走法:写侧与读侧立即覆盖;已落盘的行由 M28 补封 ——
|
|
280
313
|
* 新行的 `since` 取下一代:封口铸的落盘形盖「这一行里带值的位最新的那一代」(`credentialSlotGeneration`),读者据它判那一行用到、封过哪几位 —— 代数更早的行上新位的值一律是明文(记号本身不证明它封过新位)。
|
|
281
314
|
* M28 封的是「读口会答 `plaintext` 的每一个值」({@link credentialValueReading}),所以新加的一位上的明文在带记号的行里也被补封(只在 M28 的窗内;窗外加位要另起迁移)。
|
|
@@ -308,6 +341,22 @@ export declare const CHECKPOINT_CTX_CREDENTIAL_SLOTS: readonly [{
|
|
|
308
341
|
readonly path: readonly ["settings", "hooks", "*", "*", "hooks", "*", "plugin", "options"];
|
|
309
342
|
readonly holds: "map";
|
|
310
343
|
readonly since: 2;
|
|
344
|
+
}, {
|
|
345
|
+
readonly path: readonly ["mcpServers", "*", "transport", "command"];
|
|
346
|
+
readonly holds: "value";
|
|
347
|
+
readonly since: 3;
|
|
348
|
+
}, {
|
|
349
|
+
readonly path: readonly ["mcpServers", "*", "transport", "args"];
|
|
350
|
+
readonly holds: "value";
|
|
351
|
+
readonly since: 3;
|
|
352
|
+
}, {
|
|
353
|
+
readonly path: readonly ["settings", "hooks", "*", "*", "hooks", "*", "command"];
|
|
354
|
+
readonly holds: "value";
|
|
355
|
+
readonly since: 3;
|
|
356
|
+
}, {
|
|
357
|
+
readonly path: readonly ["settings", "hooks", "*", "*", "hooks", "*", "args"];
|
|
358
|
+
readonly holds: "value";
|
|
359
|
+
readonly since: 3;
|
|
311
360
|
}];
|
|
312
361
|
/** 本版闭集的代数 = 表里最大的 `since`(读者认得的最新一代)。落盘形的 `credentialSlotGeneration` 不大于它;大于它的行是更新的写者带着本版不认识的位写下的。 */
|
|
313
362
|
export declare const CHECKPOINT_CTX_CREDENTIAL_GENERATION: number;
|
|
@@ -337,15 +386,16 @@ export type StoredCheckpointCtx = Omit<CheckpointCtx, "body"> & {
|
|
|
337
386
|
};
|
|
338
387
|
declare const sealedCheckpointCtxBrand: unique symbol;
|
|
339
388
|
/**
|
|
340
|
-
* **封口铸出的**落盘形(品牌型):店的写口(`putCtx`)
|
|
389
|
+
* **封口铸出的**落盘形(品牌型):店的写口(`putCtx`)与一次性迁移的 ctx 行改写店腿(`rewriteCtxRows`)只收它 ⇒ 「写 ctx 只有本模块的铸点一个写入面」由型面守,
|
|
341
390
|
* 不再靠逐个数调用点(把开封形 / 裸对象直接交给写口 = 当场 tsc 红)。铸点闭集(都在本模块,都经 {@link mintSealedCheckpointCtx}):
|
|
342
|
-
* {@link sealCheckpointCtx}(新的持久化写经 {@link buildCheckpointCtx} 到它;续跑腿的写回)与 {@link
|
|
391
|
+
* {@link sealCheckpointCtx}(新的持久化写经 {@link buildCheckpointCtx} 到它;续跑腿的写回)、{@link sealStoredCheckpointCtxM28} 与 {@link rewriteStoredBodyKeys}
|
|
392
|
+
* (存量行非凭据顶层体键的改写,凭据位与读法记号原样随行)。零运行期变化。
|
|
343
393
|
*/
|
|
344
394
|
export type SealedCheckpointCtx = StoredCheckpointCtx & {
|
|
345
395
|
readonly [sealedCheckpointCtxBrand]: true;
|
|
346
396
|
};
|
|
347
397
|
/** 装配期拒启的那一句(`createHttpServer` 与起服第 6 段同调;一句、一个出口)。 */
|
|
348
|
-
export declare const CHECKPOINT_CTX_SEALING_REQUIRED = "a durable checkpoint store is wired but checkpointCtxSealing is not: suspended tasks keep the request's credentials (
|
|
398
|
+
export declare const CHECKPOINT_CTX_SEALING_REQUIRED = "a durable checkpoint store is wired but checkpointCtxSealing is not: suspended tasks keep the request's credentials (static request headers, the command lines and environment values given to MCP stdio servers and command hooks, settings.env, settings.webSearch.apiKey) in their resume context, and they are stored sealed or not at all \u2014 give the service a sealed-key store for them (this service builds it at boot in checkpoint-ctx-keys/ under the sealed-key custody directory \u2014 SEALED_KEY_DIR, default <data root>/sealed-key/; a failure there is the earlier checkpoint_ctx_sealing_unavailable warning \u2014 make that directory creatable and chmod-able by the service, or repair or remove a key file there whose public and private halves do not belong together), or, when embedding, pass checkpointCtxSealing: await ensureCheckpointCtxSealing(sealedKeyDir); refusing to start rather than write credentials in plaintext";
|
|
349
399
|
/** 封签形的判官(恰三键、三值皆串、`alg` 是本闭集那一个词)。 */
|
|
350
400
|
export declare function isSealedCheckpointValue(v: unknown): v is SealedCheckpointValue;
|
|
351
401
|
/**
|
|
@@ -388,5 +438,15 @@ export declare function sealStoredCheckpointCtxM28(stored: object, sealer: Check
|
|
|
388
438
|
readonly ctx: SealedCheckpointCtx;
|
|
389
439
|
readonly valuesSealed: number;
|
|
390
440
|
} | undefined;
|
|
441
|
+
/**
|
|
442
|
+
* 🔴 **一次性迁移对存量行非凭据顶层体键的改写**(品牌铸点之三;今天的调用方 = M30 的行改写 `stored-request-prompt-profile-m30.ts`):在一行落盘形的体上删 `drop` 里的顶层键、
|
|
443
|
+
* 设 `set` 里的顶层键,其余一个字节不动 —— 行上的读法记号(凭据封口的 `credentialSeal` / `credentialSlotGeneration` 与另两只记号)与凭据位上的值原样随行:封好的行仍是封好的,
|
|
444
|
+
* 更早写者留下的明文行仍是明文(读口照旧拒 `plaintext`,本口不替它洗白)。`drop` / `set` 碰到凭据位的根键(闭集各行路径的第一段)或 `__proto__` ⇒ 抛(程序错,不是数据错)。
|
|
445
|
+
* 体不是对象 ⇒ 抛(店的判形保证 ctx 是对象;体坏形的行由调用方先判、不交来)。
|
|
446
|
+
*/
|
|
447
|
+
export declare function rewriteStoredBodyKeys(stored: object, edit: {
|
|
448
|
+
readonly drop: readonly string[];
|
|
449
|
+
readonly set?: Readonly<Record<string, unknown>>;
|
|
450
|
+
}): SealedCheckpointCtx;
|
|
391
451
|
export {};
|
|
392
452
|
//# sourceMappingURL=checkpoint-ctx.d.ts.map
|
|
@@ -39,6 +39,28 @@ export function permissionModeReadingRefusal() {
|
|
|
39
39
|
}),
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
|
+
export const RETIRED_REQUEST_KEYS = ["promptProfile"];
|
|
43
|
+
export function retiredRequestKeyOf(body) {
|
|
44
|
+
if (body === null || typeof body !== "object" || Array.isArray(body))
|
|
45
|
+
return undefined;
|
|
46
|
+
return RETIRED_REQUEST_KEYS.find((key) => Object.hasOwn(body, key));
|
|
47
|
+
}
|
|
48
|
+
export function retiredRequestKeyRefusal(key, rewriteWindowEnd) {
|
|
49
|
+
switch (key) {
|
|
50
|
+
case "promptProfile":
|
|
51
|
+
return {
|
|
52
|
+
status: 409,
|
|
53
|
+
body: refusalBody({
|
|
54
|
+
errorCode: "checkpoint.unsupported_version",
|
|
55
|
+
message: `this task was suspended by an earlier server version and its stored request still carries promptProfile, a request key this version no longer reads (it was replaced by the boolean promptLean: classic is promptLean: false, simple is leaving promptLean out), so continuing would run the task with a prompt form it was not submitted with. Nothing was decided and nothing was resumed. If whoever operates this deployment restarts this server on or before ${rewriteWindowEnd} (UTC), the stored request is rewritten in place and the same request can be sent again; otherwise submit the work again as a new task with promptLean in place of promptProfile, and if this task is still suspended cancel it first (POST /v1/runs/:id/cancel).`,
|
|
56
|
+
}),
|
|
57
|
+
};
|
|
58
|
+
default: {
|
|
59
|
+
const unhandled = key;
|
|
60
|
+
throw new Error(`retired request key ${String(unhandled)} has no refusal sentence`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
42
64
|
export function allowListReadingUnstated(ctx) {
|
|
43
65
|
if (!bodyCarriesAllowList(ctx.body))
|
|
44
66
|
return false;
|
|
@@ -96,6 +118,8 @@ export function storedBodyReplayLogFields(refusal) {
|
|
|
96
118
|
return { kind: refusal.kind, layer: refusal.entry.layer, note: "this session's stored request carries a tool-list entry the engine reads as empty (a skill disallowedTools, an agent definition's denyTools / allowTools, the request's excludeTools / allowTools, or the rules in settings.permissions.deny / ask: a retired name, a case twin, a spelling no tool name can have, a rule core's grammar cannot compile, or a ~/ path rule on a lane with no home), or a permission list that is malformed or over the entry cap in either direction; it is not replayed — the task stays suspended until someone cancels it and resubmits with the entry fixed" };
|
|
97
119
|
case "permission_mode_reading":
|
|
98
120
|
return { kind: refusal.kind, storedMode: refusal.stored ?? null, floor: refusal.floor, note: "this session's stored request was written before the operator's AUTONOMY plan floor was recorded in the task (earlier versions re-applied it on every resume); replaying it now would run under its submitted permission mode — the task stays suspended until someone cancels it, or AUTONOMY is set to read-only so it can finish with read-only hands" };
|
|
121
|
+
case "retired_request_key":
|
|
122
|
+
return { kind: refusal.kind, key: refusal.key, note: "this session's stored request still carries a request key this version retired, and the one-time rewrite at startup did not reach it (no startup of this version inside its window since the row was written); it is not replayed — the task stays suspended until someone cancels it, or a restart of this version inside the window rewrites the row" };
|
|
99
123
|
default: {
|
|
100
124
|
const unhandled = refusal;
|
|
101
125
|
throw new Error(`stored-body replay refusal ${JSON.stringify(unhandled)} has no log fields`);
|
|
@@ -117,6 +141,10 @@ function storedBodyReplayArmAnswer(refusal, readerVersion) {
|
|
|
117
141
|
const answer = permissionModeReadingRefusal();
|
|
118
142
|
return { status: answer.status, body: { ...answer.body, ...buildCheckpointVersionKeys(refusal.writerVersion, readerVersion) } };
|
|
119
143
|
}
|
|
144
|
+
case "retired_request_key": {
|
|
145
|
+
const answer = retiredRequestKeyRefusal(refusal.key, refusal.rewriteWindowEnd);
|
|
146
|
+
return { status: answer.status, body: { ...answer.body, ...buildCheckpointVersionKeys(refusal.writerVersion, readerVersion) } };
|
|
147
|
+
}
|
|
120
148
|
default: {
|
|
121
149
|
const unhandled = refusal;
|
|
122
150
|
throw new Error(`stored-body replay refusal ${JSON.stringify(unhandled)} has no answer`);
|
|
@@ -132,6 +160,10 @@ export const CHECKPOINT_CTX_CREDENTIAL_SLOTS = [
|
|
|
132
160
|
{ path: ["settings", "webSearch", "apiKey"], holds: "value", since: 1 },
|
|
133
161
|
{ path: ["settings", "hooks", "*", "*", "hooks", "*", "headers"], holds: "map", since: 1 },
|
|
134
162
|
{ path: ["settings", "hooks", "*", "*", "hooks", "*", "plugin", "options"], holds: "map", since: 2 },
|
|
163
|
+
{ path: ["mcpServers", "*", "transport", "command"], holds: "value", since: 3 },
|
|
164
|
+
{ path: ["mcpServers", "*", "transport", "args"], holds: "value", since: 3 },
|
|
165
|
+
{ path: ["settings", "hooks", "*", "*", "hooks", "*", "command"], holds: "value", since: 3 },
|
|
166
|
+
{ path: ["settings", "hooks", "*", "*", "hooks", "*", "args"], holds: "value", since: 3 },
|
|
135
167
|
];
|
|
136
168
|
export const CHECKPOINT_CTX_CREDENTIAL_GENERATION = Math.max(...CHECKPOINT_CTX_CREDENTIAL_SLOTS.map((slot) => slot.since));
|
|
137
169
|
export const CHECKPOINT_CTX_UNSEALABLE_REASONS = ["no_key_store", "key_not_held", "unopenable", "plaintext", "unrecognized_seal"];
|
|
@@ -148,7 +180,7 @@ export class CheckpointCtxUnsealableError extends Error {
|
|
|
148
180
|
function mintSealedCheckpointCtx(sealed) {
|
|
149
181
|
return sealed;
|
|
150
182
|
}
|
|
151
|
-
export const CHECKPOINT_CTX_SEALING_REQUIRED = "a durable checkpoint store is wired but checkpointCtxSealing is not: suspended tasks keep the request's credentials (
|
|
183
|
+
export const CHECKPOINT_CTX_SEALING_REQUIRED = "a durable checkpoint store is wired but checkpointCtxSealing is not: suspended tasks keep the request's credentials (static request headers, the command lines and environment values given to MCP stdio servers and command hooks, settings.env, settings.webSearch.apiKey) in their resume context, and they are stored sealed or not at all — give the service a sealed-key store for them (this service builds it at boot in checkpoint-ctx-keys/ under the sealed-key custody directory — SEALED_KEY_DIR, default <data root>/sealed-key/; a failure there is the earlier checkpoint_ctx_sealing_unavailable warning — make that directory creatable and chmod-able by the service, or repair or remove a key file there whose public and private halves do not belong together), or, when embedding, pass checkpointCtxSealing: await ensureCheckpointCtxSealing(sealedKeyDir); refusing to start rather than write credentials in plaintext";
|
|
152
184
|
const isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
153
185
|
export function isSealedCheckpointValue(v) {
|
|
154
186
|
if (!isRecord(v))
|
|
@@ -317,4 +349,16 @@ export function sealStoredCheckpointCtxM28(stored, sealer, sessionId) {
|
|
|
317
349
|
? undefined
|
|
318
350
|
: { ctx: mintSealedCheckpointCtx({ ...stored, body: sealed, credentialSeal: CHECKPOINT_CTX_SEAL_ALG, credentialSlotGeneration: generation }), valuesSealed };
|
|
319
351
|
}
|
|
352
|
+
const CREDENTIAL_SLOT_ROOTS = new Set(CHECKPOINT_CTX_CREDENTIAL_SLOTS.map((slot) => slot.path[0]));
|
|
353
|
+
export function rewriteStoredBodyKeys(stored, edit) {
|
|
354
|
+
const touched = [...edit.drop, ...Object.keys(edit.set ?? {})];
|
|
355
|
+
const forbidden = touched.filter((key) => CREDENTIAL_SLOT_ROOTS.has(key) || key === "__proto__");
|
|
356
|
+
if (forbidden.length > 0)
|
|
357
|
+
throw new Error(`rewriteStoredBodyKeys: ${forbidden.join(", ")} is a credential-slot root (or __proto__) — a one-time body-key rewrite never touches those`);
|
|
358
|
+
const body = stored.body;
|
|
359
|
+
if (!isRecord(body))
|
|
360
|
+
throw new Error("rewriteStoredBodyKeys: the stored row's body is not an object");
|
|
361
|
+
const next = Object.fromEntries([...Object.entries(body).filter(([key]) => !edit.drop.includes(key)), ...Object.entries(edit.set ?? {})]);
|
|
362
|
+
return mintSealedCheckpointCtx({ ...stored, body: next });
|
|
363
|
+
}
|
|
320
364
|
//# sourceMappingURL=checkpoint-ctx.js.map
|
package/dist/http/dispatch.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { setSsoPrincipal,
|
|
2
|
+
import { setSsoPrincipal, setSsoScope, setSsoRole, isDestructiveSessionWrite, PRINCIPAL_TOKEN_HEADER, APPROVAL_MAC_HEADER, APPROVAL_MAC_KID_HEADER } from "../security.js";
|
|
3
3
|
import { publicStoreProbeError } from "../store-live-probe.js";
|
|
4
4
|
import { looksLikeJwt } from "@sema-agent/settings-schema/api/auth-bridge";
|
|
5
|
+
import { admitBridgeIdentity } from "../auth-bridge.js";
|
|
5
6
|
import { ROUTE_METHOD_ORDER } from "./route-ctx.js";
|
|
6
7
|
import { READ_CREDENTIAL_ROUTES, PUBLIC_ROUTES, POST_CREDENTIAL_ROUTES, routeLabel, isBillableSubmitPath, billableKindOf, isCredentialGatedRewrite, isMethodDispatchedSubmitPath, lookupRoute, isProbePath, isSubscriptionRequest } from "./route-table.js";
|
|
7
8
|
import { sendJson, sendError, isSseResponse, endSseWithError } from "./send.js";
|
|
8
9
|
import { admissionRefusalOf, readinessOf, healthReadinessKeys, sendReadyz, sendBillableRefusal, billableRefusalOf, billableRefusalFrame } from "./readiness.js";
|
|
9
10
|
import { ENGINE_SIGNAL_KEY, buildEngineSignal, fleetMembershipKeys, healthConfigLedgerKeys, healthDrainingKeys, mintEngineSignal, restartActionable } from "../fleet/engine-signal.js";
|
|
10
11
|
import { buildHealthSelfReport } from "./health-self-report.js";
|
|
11
|
-
import { actsForDeployment, authorized, systemFor, gatedPrincipal, sendPrincipalRefusal, sendUnauthorized, traceTokenPresented, verifiedIdentitySource, hasServiceAuth, devOpenDeployment } from "./principal-gate.js";
|
|
12
|
+
import { actsForDeployment, admitRunIdentity, authorized, systemFor, gatedPrincipal, sendPrincipalRefusal, sendUnauthorized, traceTokenPresented, verifiedIdentitySource, hasServiceAuth, devOpenDeployment } from "./principal-gate.js";
|
|
12
13
|
const PROCESS_STARTED_AT_MS = Date.now() - Math.round(process.uptime() * 1000);
|
|
13
14
|
export function readCredentialOk(req, config) {
|
|
14
15
|
if (!hasServiceAuth(config))
|
|
@@ -212,15 +213,14 @@ export function createDispatch(ctx) {
|
|
|
212
213
|
const authz = req.headers.authorization ?? "";
|
|
213
214
|
const rawBearer = /^Bearer\s/i.test(authz) ? authz.replace(/^Bearer\s+/i, "") : "";
|
|
214
215
|
if (rawBearer && looksLikeJwt(rawBearer)) {
|
|
215
|
-
const
|
|
216
|
-
if (
|
|
217
|
-
setSsoPrincipal(req,
|
|
218
|
-
req.headers[deps.config.principalHeader.toLowerCase()] =
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
deps.logger?.info?.("auth_bridge_principal_accepted", { principal: v.identity.principal, ...(v.identity.scope ? { scope: v.identity.scope } : {}) });
|
|
216
|
+
const identity = admitBridgeIdentity(await deps.webAdminJwtVerifier.verify(rawBearer), { logger: deps.logger, metrics: deps.metrics });
|
|
217
|
+
if (identity) {
|
|
218
|
+
setSsoPrincipal(req, identity.principal);
|
|
219
|
+
req.headers[deps.config.principalHeader.toLowerCase()] = identity.principal;
|
|
220
|
+
setSsoScope(req, identity.scope);
|
|
221
|
+
if (identity.role)
|
|
222
|
+
setSsoRole(req, identity.role);
|
|
223
|
+
deps.logger?.info?.("auth_bridge_principal_accepted", { principal: identity.principal, scope: identity.scope });
|
|
224
224
|
}
|
|
225
225
|
}
|
|
226
226
|
}
|
|
@@ -228,22 +228,27 @@ export function createDispatch(ctx) {
|
|
|
228
228
|
return;
|
|
229
229
|
if (await dispatchSegment(PUBLIC_ROUTES, req, res, url, search, method, allow.pre, ctx))
|
|
230
230
|
return;
|
|
231
|
+
const identitySource = verifiedIdentitySource(req, deps.config);
|
|
232
|
+
admitRunIdentity(req, identitySource);
|
|
231
233
|
let source = null;
|
|
232
234
|
const anyServiceAuth = hasServiceAuth(deps.config);
|
|
233
235
|
if (anyServiceAuth) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
236
|
+
switch (identitySource) {
|
|
237
|
+
case "service_token":
|
|
238
|
+
source = systemFor(req, deps.config) ?? null;
|
|
239
|
+
break;
|
|
240
|
+
case "sso":
|
|
237
241
|
source = "sso";
|
|
238
|
-
|
|
239
|
-
|
|
242
|
+
break;
|
|
243
|
+
case "direct_door_jwt":
|
|
244
|
+
case undefined:
|
|
240
245
|
sendUnauthorized(res, "credential");
|
|
241
246
|
return;
|
|
247
|
+
default: {
|
|
248
|
+
const unknownSource = identitySource;
|
|
249
|
+
throw new Error(`credential gate: identity source ${String(unknownSource)} has no gate row`);
|
|
242
250
|
}
|
|
243
251
|
}
|
|
244
|
-
else {
|
|
245
|
-
source = sys;
|
|
246
|
-
}
|
|
247
252
|
}
|
|
248
253
|
reqState.source = source;
|
|
249
254
|
if (!anyServiceAuth &&
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { RunStore } from "../plugins/store-backend.js";
|
|
2
2
|
import type { RunIdemBinding, RunRecord } from "../plugins/store-contracts.js";
|
|
3
3
|
import type { PreparedTaskSubmission, RouteCtxBase, WorkflowDecisionDelivery } from "./route-ctx.js";
|
|
4
|
+
import type { RunIdentity } from "../identity-source.js";
|
|
4
5
|
export interface DurableRunLegArgs {
|
|
5
6
|
/** `prepareSpec` 的产物,或内部车道按同一条 `resolveSpec` 装配出来的等价形。 */
|
|
6
7
|
prepared: PreparedTaskSubmission;
|
|
@@ -18,8 +19,11 @@ export interface DurableRunLegArgs {
|
|
|
18
19
|
* 提交门传 `gatedPrincipal(req) ?? null` = 提交者本人;`/decide` 的第三条车道传**卡属主**(= 原提交者,
|
|
19
20
|
* 不是代为按下按钮的 operator —— 与 resume 腿那条成文口径逐字同源)。`null` = 匿名/开放部署。 */
|
|
20
21
|
elicitOwner: string | null;
|
|
21
|
-
/** run 行元数据的 `source` 列(调用方的系统身份;内部车道传自己的车道名)
|
|
22
|
+
/** run 行元数据的 `source` 列(调用方的系统身份;内部车道传自己的车道名)。只作归因。 */
|
|
22
23
|
source: string | null;
|
|
24
|
+
/** run 行身份元组(`RunRecord.identity`)—— 调用方经 `runIdentityOf(req, config, 属主)` 读凭据门铸下的那一份交进来(本腿不碰请求);
|
|
25
|
+
* 属主 = `prepared.auth.principal`(本腿建行写进 `owner` 的同一个值)。`/decide` 第三条车道同一只读法:按下按钮的不是卡属主 ⇒ 空。 */
|
|
26
|
+
identity: RunIdentity | null;
|
|
23
27
|
/** `/decide` 第三条车道的 fresh 投递腿交来的那一件决定投递(带着的决定 + 起跑之前落行的那一笔;语义与 TRUSTED 纪律的属主 =
|
|
24
28
|
* `route-ctx.ts` 的 {@link WorkflowDecisionDelivery} 顶注)。缺席 ⇒ 只摊本会话已受理的决定行。 */
|
|
25
29
|
workflowDecision?: WorkflowDecisionDelivery;
|
|
@@ -19,7 +19,7 @@ export async function mintAndDriveDurableRun(ctx, runStore, args) {
|
|
|
19
19
|
const sessionId = args.prepared.spec.sessionId ?? uuidv7();
|
|
20
20
|
const taskId = args.clientTaskId ?? uuidv7();
|
|
21
21
|
const trustedInternals = await heldWorkflowParkDecisions(deps, sessionId, args.workflowDecision?.carried);
|
|
22
|
-
const created = await runStore.createRun(taskId, sessionId, args.prepared.auth?.principal ?? null, deps.instanceId ?? "default", { ...runMeta(args.prepared, args.source), idem: args.idem ?? null });
|
|
22
|
+
const created = await runStore.createRun(taskId, sessionId, args.prepared.auth?.principal ?? null, deps.instanceId ?? "default", { ...runMeta(args.prepared, args.source), identity: args.identity, idem: args.idem ?? null });
|
|
23
23
|
if (created.ok)
|
|
24
24
|
clearTurnActivity(taskId);
|
|
25
25
|
if (created.ok)
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* ## 规则(一条):自报位是**投影**,不是第二份规则
|
|
6
6
|
* 每一位读的是**门本身读的那只谓词 / 那只取值口**,本模块不判任何东西:
|
|
7
|
-
* · `auth.kinds` = `IDENTITY_SOURCES`(`verifiedIdentitySource`
|
|
7
|
+
* · `auth.kinds` = `IDENTITY_SOURCES`(`identity-source.ts`;`verifiedIdentitySource` 的回值闭集,序 = 判定次序)里,这台部署的装配**能**回的那几个词 —— 取唯一读法 `wiredIdentitySources`
|
|
8
8
|
* (`principal-gate.ts`;「这台部署有没有身份边界」的门 `devOpenDeployment` 读同一只):
|
|
9
9
|
* `service_token` ⇐ 全局门武装(`systemFor` 只在配了 service token 时回得出值)· `sso` ⇐ 鉴权桥装了(入口预认证只在
|
|
10
10
|
* `webAdminJwtVerifier` 在场时挂身份)· `direct_door_jwt` ⇐ 直连门开着(`verifiedIdentitySource` 那一臂的第一个合取项);
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
* 三键**恒在场**;缺席 = 老 worker(≤7.120.x)。`center.issuer` / `center.webBaseUrl` 缺席即缺席(没有鉴权桥 / 没配旋钮),不拼不猜。
|
|
34
34
|
*/
|
|
35
35
|
import type { FlatServiceDeps } from "./server.js";
|
|
36
|
-
import {
|
|
36
|
+
import type { IdentitySource } from "../identity-source.js";
|
|
37
37
|
/** `auth.identityAttach` 的词表。 */
|
|
38
38
|
export declare const IDENTITY_ATTACH_WORDS: readonly ["available", "unavailable"];
|
|
39
39
|
export type IdentityAttach = (typeof IDENTITY_ATTACH_WORDS)[number];
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** 远端可控自由文本在这几面上的长度上界(字符)。 */
|
|
2
|
+
export declare const MCP_REMOTE_TEXT_MAX = 200;
|
|
3
|
+
/** 引擎铸过的 MCP 远端失败句 → 本服务出口的形:引擎没抹的段过本仓脱敏器、引擎的记号原样,截到 {@link MCP_REMOTE_TEXT_MAX}。 */
|
|
4
|
+
export declare function redactMcpRemoteText(text: string): string;
|
|
5
|
+
//# sourceMappingURL=mcp-remote-text.d.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { redactSecrets } from "../trace/redact.js";
|
|
2
|
+
const ENGINE_REDACTION_MARK = "[redacted]";
|
|
3
|
+
export const MCP_REMOTE_TEXT_MAX = 200;
|
|
4
|
+
export function redactMcpRemoteText(text) {
|
|
5
|
+
return text.split(ENGINE_REDACTION_MARK).map((part) => redactSecrets(part)).join(ENGINE_REDACTION_MARK).slice(0, MCP_REMOTE_TEXT_MAX);
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=mcp-remote-text.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
2
|
import type { ServiceConfig } from "../config-types.js";
|
|
3
3
|
import { type DurableOwnerKey, type Principal, type SessionCaller, type SessionOwnerCell } from "../security.js";
|
|
4
|
+
import { type IdentitySource, type RunIdentity } from "../identity-source.js";
|
|
4
5
|
/** Coerce a possibly-repeated request header to a single string (or undefined). */
|
|
5
6
|
export declare function headerStr(v: string | string[] | undefined): string | undefined;
|
|
6
7
|
export declare function safeEqual(a: string, b: string): boolean;
|
|
@@ -18,19 +19,23 @@ export declare function traceTokenPresented(req: IncomingMessage, config: Servic
|
|
|
18
19
|
/** loopback 三形(IPv4 / IPv6 / IPv4-mapped)—— 一处定义,diagnostics 门与任何「本机自用」判据同吃。缺席 ⇒ false(fail-closed)。 */
|
|
19
20
|
export declare function isLoopbackAddress(addr: string | undefined): boolean;
|
|
20
21
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
22
|
+
* 🔴 **这次请求验过的身份来源 —— 全仓唯一的判定次序**:按 {@link IDENTITY_SOURCES} 的序逐词问,答第一个验得过的词(次序与它为什么是这个次序见
|
|
23
|
+
* `identity-source.ts` 头注律 1:出示了 service 凭据就是 `service_token`)。缺席 = 只有自述头或什么都没有。
|
|
24
|
+
* 读者:凭据门(`dispatch.ts`:401、归因 `source` 与 run 行身份元组读同一次的答案)、调用方信任档(`caller-trust.ts`)、门前读路谓词、
|
|
25
|
+
* off-box 诊断门(只判有无:名单只在有可验身份时才是身份,零凭据下它只是谁都能写的字符串)。
|
|
24
26
|
*/
|
|
25
|
-
export declare
|
|
26
|
-
export type IdentitySource = (typeof IDENTITY_SOURCES)[number];
|
|
27
|
+
export declare function verifiedIdentitySource(req: IncomingMessage, config: ServiceConfig): IdentitySource | undefined;
|
|
27
28
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* 缺席 = 只有自述头或什么都没有。一处判定(7.63.0 codex [high]+[medium]):off-box 读 operator 面的门用它——名单只在
|
|
31
|
-
* 有可验身份时才是身份,零凭据下它只是谁都能写的字符串;而 JWT 身份不依赖静态 token 的在场。
|
|
29
|
+
* 🔴 **run 行身份元组的唯一铸点**(律见 `identity-source.ts` 头注;唯一调用点 = `dispatch.ts` 的凭据门,机器门钉着)。`source` = 凭据门那一次
|
|
30
|
+
* {@link verifiedIdentitySource} 的答案 —— 这里不再判来源,只把来源连同它的 scope / 化身号定成元组,挂在这个请求上;建 run 行的点经 {@link runIdentityOf} 读它。
|
|
32
31
|
*/
|
|
33
|
-
export declare function
|
|
32
|
+
export declare function admitRunIdentity(req: IncomingMessage, source: IdentitySource | undefined): void;
|
|
33
|
+
/**
|
|
34
|
+
* 建 run 行时写进行里的身份元组 —— 每个 `createRun` 调用点(或替它建行的腿的调用方)读这一只,原样写入(机器门:`src/http/**` 每处 `createRun` 都写明 `identity`)。
|
|
35
|
+
* 只在**受理请求验过的主体就是这一行的属主**时交出凭据门铸下的元组(提交面恒成立:行的属主就是这个主体);别人替属主按下的那一跑(唤醒、决定投递铸的
|
|
36
|
+
* 新一跑)⇒ 空 —— 属主本人的凭据没有在这次受理里出示过(律 3)。没有请求 / 请求没过凭据门 ⇒ 空。
|
|
37
|
+
*/
|
|
38
|
+
export declare function runIdentityOf(req: IncomingMessage | undefined, config: ServiceConfig, owner: string | null): RunIdentity | null;
|
|
34
39
|
export declare function gatedPrincipal(req: IncomingMessage, config: ServiceConfig): Principal | undefined;
|
|
35
40
|
/**
|
|
36
41
|
* 「**出示了凭证但验不过** ≠ **没出示**」在 **direct-door principal JWT** 面上的形 —— 本仓
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { timingSafeEqual } from "node:crypto";
|
|
2
2
|
import { DEPLOYMENT_SHAPE_PREDICATES } from "../deployment-shape.js";
|
|
3
|
-
import { PRINCIPAL_TOKEN_HEADER, verifiedPrincipal, ssoVerifiedPrincipal, ownerlessRowOpen, mintPrincipal } from "../security.js";
|
|
3
|
+
import { PRINCIPAL_TOKEN_HEADER, verifiedPrincipal, ssoVerifiedPrincipal, ssoVerifiedScope, ownerlessRowOpen, mintPrincipal } from "../security.js";
|
|
4
|
+
import { IDENTITY_SOURCES, RUN_IDENTITY_SCOPE_MAX_CHARS } from "../identity-source.js";
|
|
4
5
|
import { sendError } from "./send.js";
|
|
5
6
|
export function headerStr(v) {
|
|
6
7
|
return Array.isArray(v) ? v[0] : v;
|
|
@@ -41,15 +42,53 @@ export function traceTokenPresented(req, config) {
|
|
|
41
42
|
export function isLoopbackAddress(addr) {
|
|
42
43
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
43
44
|
}
|
|
44
|
-
|
|
45
|
+
function identitySourceVerified(kind, req, config) {
|
|
46
|
+
switch (kind) {
|
|
47
|
+
case "service_token":
|
|
48
|
+
return systemFor(req, config) !== undefined;
|
|
49
|
+
case "sso":
|
|
50
|
+
return ssoVerifiedPrincipal(req) !== undefined;
|
|
51
|
+
case "direct_door_jwt":
|
|
52
|
+
return config.directDoorActive && verifiedPrincipal(req, config) !== undefined;
|
|
53
|
+
default: {
|
|
54
|
+
const unknownKind = kind;
|
|
55
|
+
throw new Error(`verifiedIdentitySource: unknown identity source ${String(unknownKind)}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
45
59
|
export function verifiedIdentitySource(req, config) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
60
|
+
return IDENTITY_SOURCES.find((kind) => identitySourceVerified(kind, req, config));
|
|
61
|
+
}
|
|
62
|
+
const ADMITTED_RUN_IDENTITY = new WeakMap();
|
|
63
|
+
export function admitRunIdentity(req, source) {
|
|
64
|
+
ADMITTED_RUN_IDENTITY.set(req, mintRunIdentity(req, source));
|
|
65
|
+
}
|
|
66
|
+
function mintRunIdentity(req, source) {
|
|
67
|
+
switch (source) {
|
|
68
|
+
case "service_token":
|
|
69
|
+
case "direct_door_jwt":
|
|
70
|
+
return { source, scope: null, principalInc: null };
|
|
71
|
+
case "sso": {
|
|
72
|
+
const scope = ssoVerifiedScope(req);
|
|
73
|
+
if (scope === undefined || [...scope].length > RUN_IDENTITY_SCOPE_MAX_CHARS)
|
|
74
|
+
return null;
|
|
75
|
+
return { source, scope, principalInc: null };
|
|
76
|
+
}
|
|
77
|
+
case undefined:
|
|
78
|
+
return null;
|
|
79
|
+
default: {
|
|
80
|
+
const unknownSource = source;
|
|
81
|
+
throw new Error(`admitRunIdentity: unknown identity source ${String(unknownSource)}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export function runIdentityOf(req, config, owner) {
|
|
86
|
+
if (req === undefined)
|
|
87
|
+
return null;
|
|
88
|
+
const admitted = ADMITTED_RUN_IDENTITY.get(req);
|
|
89
|
+
if (admitted === undefined || admitted === null)
|
|
90
|
+
return null;
|
|
91
|
+
return (gatedPrincipal(req, config) ?? null) === owner ? admitted : null;
|
|
53
92
|
}
|
|
54
93
|
export function gatedPrincipal(req, config) {
|
|
55
94
|
if (bearerPresentedButUnverified(req, config))
|
|
@@ -29,9 +29,8 @@
|
|
|
29
29
|
* —— `key_not_held` 多半是多副本没共享保管目录,运维修好之后同一个决定原样重发即可),**不明文回落、不丢键**。
|
|
30
30
|
* 开封要知道这一行的会话(封签绑会话)与开口(`ServiceDeps.checkpointCtxSealing`;缺席 = 本副本没有保管店):两件一起交({@link CheckpointCtxOpening})。
|
|
31
31
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* 结局里没有 `unsealable` 这一态(型面就没有;店边界的三态与开封形逐字同一段)。凭据位上的值在这种读法里仍是封签 —— 谁要用它们就必须走读法 ①。
|
|
32
|
+
* **一种读法**(第二个实参 = 开封的两件 {@link CheckpointCtxOpening}):读续跑上下文的只有续跑重建 spec 的那几条腿。7.136.0 起([ref])
|
|
33
|
+
* inbox 的展示位 `objective` 改读 run 行的目标预览,此前为它而设的第二种读法(「信封原样留着」,只读非凭据字段)随唯一的读者一起退役。
|
|
35
34
|
*/
|
|
36
35
|
import type { CheckpointCtx } from "./route-ctx.js";
|
|
37
36
|
import { type CheckpointCtxOpener, type CheckpointCtxUnsealableReason, type StoredCheckpointCtx } from "./checkpoint-ctx.js";
|
|
@@ -49,25 +48,12 @@ export type ResumeCtxRead = {
|
|
|
49
48
|
readonly field: string;
|
|
50
49
|
readonly reason: CheckpointCtxUnsealableReason;
|
|
51
50
|
};
|
|
52
|
-
/** 读法 ② 的结局:店边界的三态,`ok` 交落盘形(凭据位上仍是封签)。 */
|
|
53
|
-
export type SealedResumeCtxRead = {
|
|
54
|
-
readonly kind: "ok";
|
|
55
|
-
readonly ctx: StoredCheckpointCtx;
|
|
56
|
-
} | {
|
|
57
|
-
readonly kind: "absent";
|
|
58
|
-
} | {
|
|
59
|
-
readonly kind: "corrupt";
|
|
60
|
-
readonly where: string;
|
|
61
|
-
};
|
|
62
51
|
/** 开封的两件:这一行的会话(= 交给店 `getCtx` 的那一个)与开口(缺席 = 本副本没有保管店)。 */
|
|
63
52
|
export interface CheckpointCtxOpening {
|
|
64
53
|
readonly sessionId: string;
|
|
65
54
|
readonly opener: CheckpointCtxOpener | undefined;
|
|
66
55
|
}
|
|
67
|
-
/** 读法 ② 的词:信封原样留着(只读非凭据字段)。 */
|
|
68
|
-
export declare const KEEP_SEALED = "keep_sealed";
|
|
69
56
|
export declare function readResumeCtx(load: Promise<StoredCheckpointCtx | null>, opening: CheckpointCtxOpening): Promise<ResumeCtxRead>;
|
|
70
|
-
export declare function readResumeCtx(load: Promise<StoredCheckpointCtx | null>, opening: typeof KEEP_SEALED): Promise<SealedResumeCtxRead>;
|
|
71
57
|
/**
|
|
72
58
|
* 开不开的对外答复([ref])—— 409 `conflict.checkpoint_ctx_unsealable`,机读 `field`(哪一个凭据位,提交体路径;键名不是秘密,值从不进来)+ `reason`
|
|
73
59
|
* (闭集 `CHECKPOINT_CTX_UNSEALABLE_REASONS`)。句子说「这条任务的续跑上下文里带的凭据本服务开不开」、五种成因与出路(按 `reason` 修好保管目录后原样重发,
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { openCheckpointCtx } from "./checkpoint-ctx.js";
|
|
2
2
|
import { SqlJsonColumnError, StoreCorruptError } from "../plugins/sql-json-column.js";
|
|
3
3
|
import { refusalBody } from "./refusal-body.js";
|
|
4
|
-
export const KEEP_SEALED = "keep_sealed";
|
|
5
4
|
export async function readResumeCtx(load, opening) {
|
|
6
5
|
const read = await readStoredCtx(load);
|
|
7
|
-
if (read.kind !== "ok"
|
|
6
|
+
if (read.kind !== "ok")
|
|
8
7
|
return read;
|
|
9
8
|
const opened = openCheckpointCtx(read.ctx, opening.opener, opening.sessionId);
|
|
10
9
|
return opened.kind === "ok" ? { kind: "ok", ctx: opened.ctx } : { kind: "unsealable", field: opened.field, reason: opened.reason };
|
|
@@ -28,7 +27,7 @@ export function resumeCtxUnsealableAnswer(read) {
|
|
|
28
27
|
status: 409,
|
|
29
28
|
body: refusalBody({
|
|
30
29
|
errorCode: "conflict.checkpoint_ctx_unsealable",
|
|
31
|
-
message: "this task's stored resume context holds credentials from its request (
|
|
30
|
+
message: "this task's stored resume context holds credentials from its request (static request headers, the command lines and environment values given to MCP stdio servers and command hooks, settings.env, or settings.webSearch.apiKey) that this server cannot unseal — reason says why: no_key_store (this server has no sealed-key store), key_not_held (they were sealed with a key this server does not hold: another replica's, or a replaced sealed-key directory), unopenable (the sealed value is damaged or belongs to another session), plaintext (an older server version stored them unsealed), unrecognized_seal (a seal format this version does not know). Nothing was decided and nothing was resumed. If whoever operates this deployment restores the sealed-key directory that sealed them and restarts this server (it reads its keys only at startup), the same request can be sent again; otherwise submit the work again as a new task, and if this task is still suspended cancel it first (POST /v1/runs/:id/cancel).",
|
|
32
31
|
facts: {
|
|
33
32
|
field: read.field,
|
|
34
33
|
reason: read.reason,
|