@sema-agent/server 7.145.0 → 7.146.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 +492 -0
- package/USAGE.md +218 -47
- package/deploy/facts/CHANGES.json +25 -0
- package/deploy/facts/README.md +57 -0
- package/deploy/facts/lanes.json +54 -0
- package/deploy/facts/lanes.schema.json +57 -0
- package/deploy/facts/sandbox-rbac.json +113 -0
- package/deploy/facts/sandbox-rbac.schema.json +74 -0
- package/deploy/facts/sealed-key.json +9 -0
- package/deploy/facts/sealed-key.schema.json +52 -0
- package/deploy/sema-up/chart/templates/_helpers.tpl +19 -0
- package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +47 -7
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +4 -0
- package/deploy/sema-up/chart/templates/server.yaml +4 -0
- package/deploy/sema-up/chart/values.yaml +7 -0
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +30 -14
- package/dist/adoption/import-limits.d.ts +6 -0
- package/dist/adoption/import-limits.js +7 -0
- package/dist/adoption/import.d.ts +62 -0
- package/dist/adoption/import.js +107 -0
- package/dist/adoption/wire.d.ts +52 -0
- package/dist/adoption/wire.js +9 -0
- package/dist/approval-ask-machine.d.ts +2 -2
- package/dist/approval-card.d.ts +3 -12
- package/dist/approval-card.js +0 -4
- package/dist/approval-gate-currency.d.ts +1 -1
- package/dist/approval-gate-currency.js +1 -1
- package/dist/approval-reconciler.d.ts +1 -1
- package/dist/boot/deployment-mods.d.ts +11 -1
- package/dist/boot/deployment-mods.js +15 -2
- package/dist/boot/device-lane.js +2 -0
- package/dist/boot/engine-lease.d.ts +193 -21
- package/dist/boot/engine-lease.js +146 -20
- package/dist/boot/execution-env.d.ts +4 -0
- package/dist/boot/execution-env.js +12 -0
- package/dist/boot/exit-boundary.d.ts +50 -0
- package/dist/boot/exit-boundary.js +32 -0
- package/dist/boot/exit-last.d.ts +20 -4
- package/dist/boot/exit-last.js +21 -4
- package/dist/boot/governance-seams.js +1 -0
- package/dist/boot/memory-consolidation.d.ts +29 -17
- package/dist/boot/memory-consolidation.js +26 -15
- package/dist/boot/reapers.d.ts +12 -4
- package/dist/boot/reapers.js +39 -15
- package/dist/boot/resolve-spec.d.ts +2 -0
- package/dist/boot/resolve-spec.js +38 -15
- package/dist/boot/runner-deps.js +1 -1
- package/dist/boot/session-faces.js +3 -1
- package/dist/boot/shutdown.js +27 -9
- package/dist/boot/stage-01-config.js +1 -1
- package/dist/boot/stage-03-store-backend.d.ts +1 -0
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -0
- package/dist/boot/stage-05-execution-env.d.ts +3 -0
- package/dist/boot/stage-05-execution-env.js +3 -3
- package/dist/boot/stage-06-runners.d.ts +3 -0
- package/dist/boot/stage-06-runners.js +11 -10
- package/dist/boot/stage-07-capability-layer.d.ts +3 -0
- package/dist/boot/stage-07-capability-layer.js +7 -2
- package/dist/boot/stage-08-reapers.d.ts +3 -0
- package/dist/boot/stage-08-reapers.js +3 -3
- package/dist/boot/stage-09-leader.d.ts +3 -0
- package/dist/boot/stage-10-http-server.d.ts +3 -0
- package/dist/boot/stage-10-http-server.js +3 -2
- package/dist/boot/stores.d.ts +1 -0
- package/dist/boot/stores.js +35 -19
- package/dist/boot/workflow-orchestration.d.ts +1 -1
- package/dist/boot/workflow-orchestration.js +2 -1
- package/dist/capabilities/composite-members.d.ts +3 -1
- package/dist/capabilities/composite-members.js +3 -1
- package/dist/capabilities/scenarios.d.ts +2 -2
- package/dist/capability-facts.d.ts +18 -1
- package/dist/capability-facts.js +25 -7
- package/dist/checkpoint-ctx-seal-m28.d.ts +1 -1
- package/dist/config-catalog.js +13 -4
- package/dist/config-provider.d.ts +2 -2
- package/dist/config-types.d.ts +43 -4
- package/dist/config.d.ts +6 -1
- package/dist/config.js +67 -11
- package/dist/deleted-session-ids.d.ts +19 -0
- package/dist/deleted-session-ids.js +26 -0
- package/dist/deploy-facts.d.ts +155 -0
- package/dist/deploy-facts.js +94 -0
- package/dist/device-ws-hub.d.ts +48 -3
- package/dist/device-ws-hub.js +48 -2
- package/dist/error-code-family.d.ts +35 -0
- package/dist/error-code-family.js +26 -0
- package/dist/fleet/drain-entry.d.ts +39 -3
- package/dist/fleet/drain-entry.js +6 -0
- package/dist/fleet/fleet-bus.d.ts +2 -1
- package/dist/hooks/branch-transcript.d.ts +1 -1
- package/dist/hooks/branch-transcript.js +1 -0
- package/dist/hooks/classic-stations.d.ts +25 -8
- package/dist/hooks/classic-stations.js +29 -3
- package/dist/hooks/hook-runner.d.ts +33 -16
- package/dist/hooks/hook-runner.js +166 -73
- package/dist/hooks/hook-source.d.ts +14 -2
- package/dist/hooks/hook-source.js +8 -0
- package/dist/http/active-run-conflict.d.ts +1 -1
- package/dist/http/active-run-conflict.js +1 -1
- package/dist/http/admission.js +11 -1
- package/dist/http/checkpoint-ctx.d.ts +59 -71
- package/dist/http/checkpoint-ctx.js +34 -40
- package/dist/http/dispatch.js +18 -2
- package/dist/http/durable-run-leg.d.ts +5 -0
- package/dist/http/durable-run-leg.js +1 -0
- package/dist/http/execution-context.d.ts +4 -0
- package/dist/http/execution-context.js +9 -0
- package/dist/http/health-self-report.d.ts +6 -2
- package/dist/http/health-self-report.js +3 -2
- package/dist/http/memory-compliance-failure-reply.d.ts +1 -1
- package/dist/http/memory-compliance-failure-reply.js +2 -15
- package/dist/http/memory-control-plane-corrupt-reply.d.ts +25 -0
- package/dist/http/memory-control-plane-corrupt-reply.js +19 -0
- package/dist/http/principal-gate.d.ts +35 -12
- package/dist/http/principal-gate.js +16 -12
- package/dist/http/request-guards.d.ts +1 -1
- package/dist/http/request-guards.js +5 -5
- package/dist/http/resume-legs.d.ts +22 -0
- package/dist/http/resume-legs.js +26 -17
- package/dist/http/route-ctx.d.ts +11 -10
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/adoption.d.ts +11 -0
- package/dist/http/routes/adoption.js +80 -6
- package/dist/http/routes/agents-roster.js +1 -0
- package/dist/http/routes/approvals-assistant.js +2 -1
- package/dist/http/routes/background.js +1 -0
- package/dist/http/routes/capabilities.js +4 -1
- package/dist/http/routes/diagnostics.d.ts +9 -14
- package/dist/http/routes/diagnostics.js +10 -20
- package/dist/http/routes/engine.d.ts +31 -0
- package/dist/http/routes/engine.js +81 -0
- package/dist/http/routes/memory-bundle.js +3 -0
- package/dist/http/routes/memory-consolidation.js +3 -5
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/memory-origin.js +2 -4
- package/dist/http/routes/memory-policy.js +5 -1
- package/dist/http/routes/observability.js +3 -6
- package/dist/http/routes/runs.js +7 -3
- package/dist/http/routes/session-sync.js +12 -25
- package/dist/http/routes/sessions-list.d.ts +1 -1
- package/dist/http/routes/sessions.js +4 -0
- package/dist/http/routes/tasks.js +23 -5
- package/dist/http/routes/trace-usage.js +1 -1
- package/dist/http/run-concurrency-cap.d.ts +86 -0
- package/dist/http/run-concurrency-cap.js +54 -0
- package/dist/http/server.d.ts +15 -12
- package/dist/http/server.js +18 -3
- package/dist/http/stored-body-replay.d.ts +9 -6
- package/dist/http/stored-body-replay.js +19 -5
- package/dist/http/wire-types.d.ts +8 -3
- package/dist/json-body-limit.d.ts +8 -0
- package/dist/json-body-limit.js +2 -0
- package/dist/leader/diffout.d.ts +1 -1
- package/dist/local-data-root.d.ts +2 -2
- package/dist/memory-operator-faces.d.ts +9 -4
- package/dist/memory-scope-stores.d.ts +9 -7
- package/dist/memory-scope-stores.js +3 -14
- package/dist/memory-scope.d.ts +36 -0
- package/dist/memory-scope.js +32 -1
- package/dist/net-address.d.ts +53 -0
- package/dist/net-address.js +111 -0
- package/dist/observability/fail-open.d.ts +14 -10
- package/dist/observability/fail-open.js +14 -10
- package/dist/orchestration/workflow-notify-journal.js +2 -3
- package/dist/org-delivery-gate.js +1 -1
- package/dist/peer-directory.d.ts +6 -12
- package/dist/peer-directory.js +5 -1
- package/dist/plugins/caching-session-store.d.ts +3 -1
- package/dist/plugins/caching-session-store.js +3 -0
- package/dist/plugins/checkpoint-store-face.d.ts +426 -0
- package/dist/plugins/checkpoint-store-face.js +152 -0
- package/dist/plugins/file-run-store.d.ts +0 -6
- package/dist/plugins/file-run-store.js +1 -12
- package/dist/plugins/fork-routing-session-store.d.ts +6 -2
- package/dist/plugins/fork-routing-session-store.js +2 -2
- package/dist/plugins/imported-layer-root-retirement.d.ts +10 -8
- package/dist/plugins/local-checkpoint-store.d.ts +2 -2
- package/dist/plugins/local-checkpoint-store.js +2 -1
- package/dist/plugins/local-session-store.d.ts +28 -5
- package/dist/plugins/local-session-store.js +32 -8
- package/dist/plugins/memory-engine-pg.d.ts +29 -6
- package/dist/plugins/memory-engine-pg.js +96 -214
- package/dist/plugins/memory-engine-sql-apply.d.ts +121 -0
- package/dist/plugins/memory-engine-sql-apply.js +358 -0
- package/dist/plugins/memory-engine-tidb.d.ts +35 -9
- package/dist/plugins/memory-engine-tidb.js +97 -227
- package/dist/plugins/memory-key-guards.d.ts +1 -1
- package/dist/plugins/memory-origin-law.d.ts +3 -3
- package/dist/plugins/one-time-migrations.d.ts +32 -56
- package/dist/plugins/one-time-migrations.js +25 -117
- package/dist/plugins/permission-rule-store-file.d.ts +17 -3
- package/dist/plugins/permission-rule-store-file.js +8 -1
- package/dist/plugins/pg-pool.js +1 -1
- package/dist/plugins/pg-session-storage.d.ts +17 -4
- package/dist/plugins/pg-session-storage.js +8 -4
- package/dist/plugins/run-store-sql.js +2 -2
- package/dist/plugins/schema-ensure-legs.js +2 -2
- package/dist/plugins/session-fork.d.ts +31 -9
- package/dist/plugins/session-fork.js +3 -2
- package/dist/plugins/session-placement.d.ts +4 -2
- package/dist/plugins/sql-json-column.d.ts +5 -1
- package/dist/plugins/store-backend.d.ts +11 -8
- package/dist/plugins/store-backend.js +8 -7
- package/dist/plugins/store-contracts.d.ts +1 -11
- package/dist/plugins/store-contracts.js +0 -9
- package/dist/plugins/store-sweep.d.ts +63 -0
- package/dist/plugins/store-sweep.js +48 -0
- package/dist/plugins/tidb-pool.js +1 -1
- package/dist/plugins/tidb-session-store.d.ts +16 -3
- package/dist/plugins/tidb-session-store.js +8 -4
- package/dist/prompt-screen.d.ts +6 -9
- package/dist/prompt-screen.js +2 -5
- package/dist/rules-consent.d.ts +20 -27
- package/dist/rules-consent.js +82 -6
- package/dist/run-cancel-context.d.ts +4 -1
- package/dist/run-cancel-context.js +2 -1
- package/dist/runs.js +1 -1
- package/dist/sandbox-egress-policy.js +6 -11
- package/dist/sandbox-rbac-rules.d.ts +88 -0
- package/dist/sandbox-rbac-rules.js +80 -0
- package/dist/sealed-key-layout.d.ts +17 -0
- package/dist/sealed-key-layout.js +4 -0
- package/dist/sealed-key.js +5 -5
- package/dist/security.d.ts +38 -6
- package/dist/security.js +9 -2
- package/dist/session-notify-door.d.ts +5 -3
- package/dist/session-resident-background.d.ts +57 -0
- package/dist/session-resident-background.js +20 -0
- package/dist/session-sync-kernel.d.ts +53 -14
- package/dist/session-sync-kernel.js +70 -1
- package/dist/session-sync.d.ts +5 -3
- package/dist/session-workspace.d.ts +1 -0
- package/dist/session-workspace.js +1 -0
- package/dist/sighup-idle.d.ts +9 -7
- package/dist/sighup-idle.js +4 -5
- package/dist/spec-fields.d.ts +16 -0
- package/dist/spec-fields.js +7 -0
- package/dist/stored-request-env-credentials-m38.d.ts +3 -0
- package/dist/stored-request-env-credentials-m38.js +8 -0
- package/dist/stored-request-prompt-profile-m30.d.ts +1 -1
- package/dist/{plugins → stores-sql}/checkpoint-store-sql.d.ts +13 -427
- package/dist/{plugins → stores-sql}/checkpoint-store-sql.js +33 -194
- package/dist/{plugins → stores-sql}/mailbox-store-sql.d.ts +2 -2
- package/dist/{plugins → stores-sql}/mailbox-store-sql.js +4 -4
- package/dist/{plugins → stores-sql}/roster-store-sql.d.ts +2 -2
- package/dist/{plugins → stores-sql}/roster-store-sql.js +1 -1
- package/dist/{plugins → stores-sql}/tool-result-store-sql.d.ts +2 -2
- package/dist/{plugins → stores-sql}/tool-result-store-sql.js +6 -6
- package/dist/{plugins → stores-sql}/workflow-journal-store-sql.d.ts +7 -12
- package/dist/{plugins → stores-sql}/workflow-journal-store-sql.js +3 -8
- package/dist/task-settings.d.ts +59 -4
- package/dist/task-settings.js +50 -4
- package/dist/tool-approval.d.ts +2 -2
- package/dist/trace/core-keyset-guard.d.ts +8 -7
- package/dist/trace/engine-notice-wire.d.ts +1 -1
- package/dist/trace/engine-notice-wire.js +2 -0
- package/dist/trace/exit-seat.d.ts +6 -0
- package/dist/trace/exit-seat.js +1 -0
- package/dist/trace/project.js +9 -0
- package/dist/trace/redact.d.ts +13 -2
- package/dist/trace/redact.js +305 -24
- package/dist/trace/self-minted-wire.d.ts +326 -8
- package/dist/trace/self-minted-wire.js +125 -7
- package/dist/trace/wire-projection-faces.d.ts +1 -1
- package/dist/trace/wire-projection-faces.js +1 -1
- package/dist/usage-analytics.d.ts +4 -0
- package/package.json +12 -4
- package/scripts/drain-check-local.mjs +8 -29
- package/scripts/drain-check.mysql.sql +3 -24
- package/scripts/drain-check.pg.sql +3 -24
- package/skills/update-config.md +1 -1
- package/wire-changes/server@7.146.0.json +3221 -0
- package/dist/approval-batch-census.d.ts +0 -27
- package/dist/approval-batch-census.js +0 -27
package/dist/http/admission.js
CHANGED
|
@@ -2,7 +2,8 @@ import { APPROVAL_REACH, IMAGE_ADMISSION, isApprovalReach, isPermissionMode, isT
|
|
|
2
2
|
import { isAtMentionable, matchCatalogModel, refusedCatalogEntry, selectableCatalog } from "../model-select.js";
|
|
3
3
|
import { echoModelRef, modelUnavailableMessage } from "../model-entry-refusal.js";
|
|
4
4
|
import { HttpError, sessionIdShapeIssue } from "../security.js";
|
|
5
|
-
import { MAX_SETTINGS_OUTPUT_STYLE_CHARS, MAX_SETTINGS_ENV_VARS, MAX_SETTINGS_ENV_KEY_CHARS, MAX_SETTINGS_ENV_VALUE_CHARS, PERMISSION_MODE_WORDS, parseTaskSettings, settingsPermissionBucketIssue, skillListingBudgetFractionOk, skillListingMaxDescOk, hooksKeyIssue, taskHooksHonored, taskSettingsKeyIssue } from "../task-settings.js";
|
|
5
|
+
import { MAX_SETTINGS_OUTPUT_STYLE_CHARS, MAX_SETTINGS_ENV_VARS, MAX_SETTINGS_ENV_KEY_CHARS, MAX_SETTINGS_ENV_VALUE_CHARS, PERMISSION_MODE_WORDS, autoCompactEnabledOk, parseTaskSettings, readSettingsEnv, settingsEnvCredentialIssue, settingsPermissionBucketIssue, skillListingBudgetFractionOk, skillListingMaxDescOk, hooksKeyIssue, taskHooksHonored, taskSettingsKeyIssue } from "../task-settings.js";
|
|
6
|
+
import { serverCredentialValueSources } from "../server-secret-env.js";
|
|
6
7
|
import { tightenOnlySeatIssue } from "../tighten-only-seats.js";
|
|
7
8
|
import { approvalFrameFamiliesIssue } from "../tool-approval.js";
|
|
8
9
|
import { buildEntryModeClampNotice } from "../entry-mode-clamp-notice.js";
|
|
@@ -284,6 +285,11 @@ export function createAdmission(ctx) {
|
|
|
284
285
|
return null;
|
|
285
286
|
}
|
|
286
287
|
}
|
|
288
|
+
const credentialIssue = settingsEnvCredentialIssue(readSettingsEnv(st).reaching, serverCredentialValueSources(deps.config.modelApiKeyEnv));
|
|
289
|
+
if (credentialIssue !== null) {
|
|
290
|
+
sendError(res, 400, "request.env_credential_refused", credentialIssue.message, { ...credentialIssue.fields });
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
287
293
|
}
|
|
288
294
|
if (st.ultracode !== undefined && typeof st.ultracode !== "boolean") {
|
|
289
295
|
sendError(res, 400, "request.field_invalid", "settings.ultracode must be a boolean");
|
|
@@ -297,6 +303,10 @@ export function createAdmission(ctx) {
|
|
|
297
303
|
sendError(res, 400, "request.field_invalid", "settings.skillListingMaxDescChars must be a positive integer");
|
|
298
304
|
return null;
|
|
299
305
|
}
|
|
306
|
+
if (st.autoCompactEnabled !== undefined && !autoCompactEnabledOk(st.autoCompactEnabled)) {
|
|
307
|
+
sendError(res, 400, "request.field_invalid", "settings.autoCompactEnabled must be a boolean");
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
300
310
|
if (st.hooks !== undefined && st.hooks !== null) {
|
|
301
311
|
const hooksParsed = parseHooksConfig(st.hooks);
|
|
302
312
|
if (!hooksParsed.config) {
|
|
@@ -1,27 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 续跑重建输入(`checkpoint_ctx` 的行体,{@link CheckpointCtx})
|
|
2
|
+
* 续跑重建输入(`checkpoint_ctx` 的行体,{@link CheckpointCtx})的**写形**,以及「这条停驻行的持久化体在本版上能否重放」的四问与它们的答复。
|
|
3
3
|
*
|
|
4
|
-
* ##
|
|
5
|
-
* `settings.permissions.allow` 的读法换过两次:≤7.114.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* ## allow 读法问(常设规则,按行的写者版本;不是迁移、不读记号)
|
|
5
|
+
* `settings.permissions.allow` 的读法换过两次:≤7.114.x 是「名单」(名单外的工具一律拒);7.115.0–7.116.x 是「表态」(只回答没人表态的那一问);
|
|
6
|
+
* 7.117.0 起整份交给引擎的 allow 层(表里的调用免问)。续跑家族把**持久化的提交体**原样重放进 `resolveSpec` —— 7.117.0 之前写下、体里带非空 `allow` 的行
|
|
7
|
+
* 按今天的读法重放 = 静默放宽(名单外的工具放开 / 普通问不再问)。⇒ 规则一句:**体里 `allow` 在生效(非空数组,{@link bodyCarriesAllowList})而行的写者版本
|
|
8
|
+
* 证不出 ≥ {@link ALLOW_LAYER_READING_SINCE}(`CheckpointCtx.writerVersion` 缺席、读不出,或早于它)⇒ 拒**({@link allowListReadingRefusal},409 `checkpoint.unsupported_version`,行字节不动)。
|
|
9
|
+
* · 证据只有一个源:行上的写者版本(`route-ctx.ts` `CheckpointCtx.writerVersion`;7.124.0 起每一次写都带)。7.117.0–7.145.x 写过的 allow 读法记号
|
|
10
|
+
* 不是本问的读者 —— 记号写点已删(一次性迁移 M7 退役)、键在存量行上无人读;7.117.0–7.123.x 写下、带非空 `allow` 的行没有写者版本,同样拒(证不出;fail-closed)。
|
|
11
|
+
* · 写者版本因此是本问的拒因,而它的写点必须守住同一条律:**盖写者版本的写只发生在本进程按当前读法读过这份体之后** —— 新提交(受理门按当前读法读)、
|
|
12
|
+
* 或已经过了本判据的续跑腿写回(`resume-legs.ts` `commitResumeCtx`、在飞 run 的切档写回)。在判据之前盖版本 = 把一条旧行洗成新行。
|
|
13
|
+
* · 没有期限:日历窗关不证明旧行不在(留存拉长、备份恢复、`APPROVAL_TERMINAL_BACKSTOP_MS` 调长),所以这一问常设,不进一次性迁移登记表。
|
|
9
14
|
*
|
|
10
|
-
* ##
|
|
11
|
-
*
|
|
12
|
-
* 行留停驻、字节不动(拒发生在认领之前,run 行、卡、ctx 一个字节都不写);出路 = 作为新任务重提,这条任务若还停驻着先取消(`task_done` 唤醒停驻与 workflow 宿主那条腿没有可取消的 run)。
|
|
13
|
-
* **没有**「按旧读法继续读」的臂(那是第二种读法),也**没有**「按新读法静默续跑」的臂(那是对一条已提交任务的静默放宽)。
|
|
14
|
-
* · 记号 = 当前写点在体里带非空 `allow` 时写在 ctx 上的 `permissionsAllowReading`,闭集只有当前读法一个词({@link PERMISSIONS_ALLOW_READINGS})。
|
|
15
|
-
* 写点 = 每一次**新的**持久化写({@link buildCheckpointCtx} 是它们的唯一构造口);续跑腿的写回传的是读进来的那只 ctx(或其展开),记号随行,不重新判。
|
|
16
|
-
* · 拒句按「这行是在哪种读法下写的」分两句({@link ALLOW_LIST_READING_ERAS} 穷举):无记号(或记号认不得)= 名单时代;`"statement"` = 表态时代。
|
|
17
|
-
* · 体里没有 `allow`(或空数组 —— 三代都把空数组读成「没有」)的行不写记号、不受本规则影响。
|
|
18
|
-
*
|
|
19
|
-
* ## 第二问(7.117.0 起,引擎 7.42 逐字读规则条目;7.131.0 起覆盖全部工具名清单):工具名清单读成空的存量体
|
|
20
|
-
* 同一面上的第二个「新提交会被拒、存量体重放不能放过」:提交体里工具名清单 —— 技能(顶层 / 子代)的 `disallowedTools`(7.117.0:`"Bash "` 这类 7.41 去白后有效、
|
|
15
|
+
* ## 工具名清单问(7.117.0 起,引擎 7.42 逐字读规则条目;7.131.0 起覆盖全部工具名清单):工具名清单读成空的存量体
|
|
16
|
+
* 「新提交会被拒、存量体重放不能放过」:提交体里工具名清单 —— 技能(顶层 / 子代)的 `disallowedTools`(7.117.0:`"Bash "` 这类 7.41 去白后有效、
|
|
21
17
|
* 7.42 什么也不拒的条目)、子代定义的 `denyTools` / `allowTools`、顶层 `excludeTools` / `allowTools`(7.131.0:限制侧近似名 / 大小写孪生、退役名、文法读不出,放行侧只近似名)—— 有引擎读成空的条目 ⇒ 提交 400(`resolveSpec`,拒点);
|
|
22
18
|
* 存量停驻体重放 ⇒ 409 `resume_blocked_by_policy`(`blockedBy` = 该层的拒码)。判据函数 = `rule-entry-list.ts` `inertToolListEntryOf`。
|
|
23
19
|
*
|
|
24
|
-
* ##
|
|
20
|
+
* ## 模式词问(7.122.0):体里模式词的读法记号
|
|
25
21
|
* 7.122.0 起一条 run 的模式词只有一个源 —— 存储的提交体顶层 `permissionMode`(提交入口把运维 `AUTONOMY=plan` 的地板盖进去一次;`plan_review` 写回改它),
|
|
26
22
|
* 治理层不再在每一次续跑重钳。更早版本写下的行体里是**请求的原词**,运维的 plan 由治理层每段重新折上(7.121.x 及以前:只读手 + 写面 roots)。
|
|
27
23
|
* 那种行在本版上按体里的原词重放 = 静默放宽(`acceptEdits` / `bypassPermissions` 原词直接生效;无词 ⇒ 引擎读 checkpoint 记下的词)。
|
|
@@ -31,62 +27,63 @@
|
|
|
31
27
|
* 不受影响:那两种行在新旧两种读法下答同一个词。出路:作为新任务重提(仍停驻的先取消),或在它们收尾之前把 `AUTONOMY` 设成 `read-only`(按段的只读围栏,
|
|
32
28
|
* 与 7.121.x 的 `AUTONOMY=plan` 同一个结局,且没有入口地板 ⇒ 不拒)。删除条件登记在 `plugins/one-time-migrations.ts` 的 M12 行。
|
|
33
29
|
*
|
|
34
|
-
* ##
|
|
30
|
+
* ## 退役请求键问(7.137.0):体里的退役请求键
|
|
35
31
|
* 请求键退役之后({@link RETIRED_REQUEST_KEYS}:今天两只 —— `promptProfile` 换成布尔 `promptLean`,`rewindFiles` 是退役的旧文件还原拼法),新提交带它在键闭集门 400。存体里的旧键怎么办,闭集里每个键有
|
|
36
32
|
* **一个处置格**,住在哪张表就是哪个处置:**拒**表({@link REPLAY_REFUSED_RETIRED_KEYS},今天 `promptProfile`)是塑形过任务本身的键,**惰性**表({@link INERT_RETIRED_KEYS},今天 `rewindFiles`)是一次性键。
|
|
37
33
|
* · 拒表的键:存体里的旧键由一次性迁移在起服时原地改写
|
|
38
34
|
* (M30,`stored-request-prompt-profile-m30.ts`,行改写经本模块的 {@link rewriteStoredBodyKeys})。改写不到的残留行(窗内从没起过服的部署;起服扫描之后滚动升级里
|
|
39
|
-
* 旧副本才写下的行)体里仍带旧键 ⇒ 拒({@link retiredRequestKeyRefusal}
|
|
35
|
+
* 旧副本才写下的行)体里仍带旧键 ⇒ 拒({@link retiredRequestKeyRefusal},码同模式词读法拒:`checkpoint.unsupported_version`)。**没有**续跑时按旧键读的第二种读法,
|
|
40
36
|
* 也**没有**「旧键无人读、静默续跑」的臂:旧键还在 = 这份体没被改写过,它当年要的形本版读不出来。
|
|
41
37
|
* · 惰性表的键:一次性键 —— 只在提交的那一拍起作用(文件还原的一次性动作),续跑重建里没有任何一条腿读它,存体里留着它不要求任何事、不改变重放要做的事 ⇒ 不拒、不改写、续跑照常。
|
|
42
38
|
* 这不是上面那条「旧键无人读、静默续跑」的臂:那一臂的前提是读不出旧键会让续跑做一件提交时没要的事,惰性格的判据恰是「没有这个键,重放做的事一字不差」。
|
|
43
39
|
* 加一个退役键必须选格 —— 进拒表 ⇒ {@link retiredRequestKeyRefusal} 的 switch 与 `stored-body-replay.ts` 的迁移 id 表编译红,直到给它一句拒句和改写它的迁移;进惰性表 ⇒ 改动里要写明它为什么是一次性的。
|
|
44
40
|
*
|
|
45
41
|
* ## 一只判据、五个问点(`http/stored-body-replay.ts` 的 `storedBodyReplayRefusal` / 本模块的 {@link storedBodyReplayAnswer})
|
|
46
|
-
*
|
|
47
|
-
*
|
|
42
|
+
* 「这条停驻行的持久化体在本版上能否重放」只有**一个**读法:上面四问(加 `settings.env` 凭据那一臂,规则在 `stored-request-env-credentials-m38.ts`)合在 `stored-body-replay.ts` 的 `storedBodyReplayRefusal` 一处(allow 读法问的谓词在本模块;工具名清单问另读请求设置的解析层与
|
|
43
|
+
* 执行车道 / 配置根两个属主、模式词问读请求设置与治理两个属主 —— 本模块的值依赖要留在 node 内建 / 引擎包根之内,随包排空脚本经编译产物读它),答复合在 {@link storedBodyReplayAnswer} 一处。
|
|
48
44
|
* 问点五个,同调同答:续跑驱动段(`resume-legs.ts` `resolveResumeSpecOrBlocked`,另四条腿的唯一判点)· plan_review 的 prepare 段(读类拒,在 nonce 消费之前)·
|
|
49
45
|
* SLA 拒扫腿的跳过臂(`approval-sweeps.ts`)· 终态 run 的 steer 铸唤醒卡之前(`routes/runs.ts`:铸卡前先证明它赎得回,证不出 ⇒ 不铸、当场同一个拒)·
|
|
50
46
|
* `resolveSpec` 本身留作真正的拒点(提交腿 400;续跑腿在到它之前已被本判据答掉)。再开第六个问点必须调这两只,不许各判各的 —— 此前铸卡前只判了
|
|
51
|
-
*
|
|
47
|
+
* 一问,工具名清单那一问漏在外面,卡铸出来了、`/wake` 恒 409([ref] 合并复审两腿同报)。
|
|
52
48
|
*
|
|
53
49
|
* ## 凭据位密封(7.134.0;常设规则,不是迁移)
|
|
54
50
|
* 体里请求面凭据位上的值在 ctx 里只以封签存在 —— 写:{@link buildCheckpointCtx} / {@link sealCheckpointCtx} 一只封口;读:续跑上下文读口里一只开口
|
|
55
51
|
* {@link openCheckpointCtx};开不开 ⇒ `409 conflict.checkpoint_ctx_unsealable`。规则全文在本文件末段「凭据位密封」的头注。
|
|
56
|
-
*
|
|
57
|
-
* ## 何时删(一次性迁移,不是长期双读)
|
|
58
|
-
* 本判据、拒臂、记号写点与 `CheckpointCtx.permissionsAllowReading` 一起删,删除条件与窗登记在 `plugins/one-time-migrations.ts` 的
|
|
59
|
-
* 一次性迁移登记表(本条那一行):所有旧读法下停驻的行都已结束或被收割(停驻行的终局 = 落盘起 `TERMINAL_BACKSTOP_MS`,见
|
|
60
|
-
* `plugins/checkpoint-store-sql.ts`)之后的那个版本。删的时候记号的读者一起删。
|
|
61
52
|
*/
|
|
62
53
|
import type { PermissionMode } from "@sema-agent/core";
|
|
63
54
|
import type { CheckpointCtx } from "./route-ctx.js";
|
|
64
55
|
import type { TaskRequestBody } from "./wire-types.js";
|
|
65
56
|
import type { InertToolListEntry } from "../rule-entry-list.js";
|
|
66
57
|
import { type Refusal } from "./refusal-body.js";
|
|
67
|
-
/**
|
|
68
|
-
|
|
69
|
-
export declare const PERMISSIONS_ALLOW_READINGS: readonly ["allow_layer"];
|
|
70
|
-
export type PermissionsAllowReading = (typeof PERMISSIONS_ALLOW_READINGS)[number];
|
|
71
|
-
/** 体里模式词的读法记号闭集(一词 = 当前读法):这一行体的顶层 `permissionMode` 是这条 run 模式词**唯一的源**(提交入口盖过运维地板、`plan_review` 写回改它),
|
|
72
|
-
* 续跑照它读、不再由治理层按段重钳。写点两个 = {@link buildCheckpointCtx}(每一次新的持久化写都写)与 {@link withPermissionModeRewritten}(`plan_review` 写回改词的那一拍写);
|
|
73
|
-
* **不改词**的续跑腿写回传原 ctx ⇒ 记号随行。 */
|
|
74
|
-
export declare const PERMISSION_MODE_READINGS: readonly ["entry_word"];
|
|
75
|
-
export type PermissionModeReading = (typeof PERMISSION_MODE_READINGS)[number];
|
|
76
|
-
/** 被拒的行是在哪种读法下写的(闭集;拒句按它穷举):`list` = 无记号或记号认不得(≤7.114.0 的名单读法;认不得的记号不是任何一代的证据,
|
|
77
|
-
* 按最早那一代说话);`statement` = 7.115.0–7.116.x 写下的表态读法。 */
|
|
78
|
-
export declare const ALLOW_LIST_READING_ERAS: readonly ["list", "statement"];
|
|
79
|
-
export type AllowListReadingEra = (typeof ALLOW_LIST_READING_ERAS)[number];
|
|
58
|
+
/** allow 层读法从这一版起(7.117.0):此前的写者对 `settings.permissions.allow` 是另一种读法(≤7.114.x 名单 / 7.115.0–7.116.x 表态)。规则见顶注「allow 读法问」。 */
|
|
59
|
+
export declare const ALLOW_LAYER_READING_SINCE = "7.117.0";
|
|
80
60
|
/**
|
|
81
61
|
* 体里的 `settings.permissions.allow` 是否**在生效**:非空数组(三代同一个「在」—— 空数组 = 没有)。
|
|
82
62
|
* 入参是持久化的 JSON(可能来自任何旧版本),逐层判形,不信型面。
|
|
83
63
|
*/
|
|
84
64
|
export declare function bodyCarriesAllowList(body: TaskRequestBody): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* 行的写者版本**证得出** ≥ {@link ALLOW_LAYER_READING_SINCE}:在场、读得出、三段数不小于它(三段相等时预发布算在它之前 —— semver 序,失效关闭方向)。
|
|
67
|
+
* 缺席 / 读不出(`"unknown"`、前导零、空标识段这类不合 SemVer 文法的串)/ 更早 ⇒ `false`。入参是持久化的 JSON,不信型面。
|
|
68
|
+
*/
|
|
69
|
+
export declare function writerReadsAllowLayer(writerVersion: unknown): boolean;
|
|
70
|
+
/** allow 读法问(顶注):体里 `allow` 在生效而写者版本证不出 ≥ {@link ALLOW_LAYER_READING_SINCE} ⇒ `true`(拒)。 */
|
|
71
|
+
export declare function allowListWriterUnproven(ctx: CheckpointCtx): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* allow 读法问的拒答复 —— 码 `checkpoint.unsupported_version`,409(卡仍 pending 时的 `retriable:true` 由 {@link resumeRefusalWithCard} 追加,本铸点不带;
|
|
74
|
+
* 两版本键由 {@link storedBodyReplayAnswer} 按那一码的键律补)。拒在认领之前,没有 `taskId`。句子一句:写者证不出是哪种读法(早于 7.117.0,或没记下版本 —— 7.124.0 之前的写者都不记),
|
|
75
|
+
* 两种旧读法各是什么、照今天的读法续跑会放宽什么,出路(作为新任务重提,仍停驻的先取消)。
|
|
76
|
+
* 🔴 形是给冻结门看的:`status: <三位数>, body: refusalBody({ errorCode: "<码>", message: "<整句双引号字面>"`,中间只许有空白。
|
|
77
|
+
*/
|
|
78
|
+
export declare function allowListReadingRefusal(): ResumeRefusalAnswer;
|
|
79
|
+
/** 体里模式词的读法记号闭集(一词 = 当前读法):这一行体的顶层 `permissionMode` 是这条 run 模式词**唯一的源**(提交入口盖过运维地板、`plan_review` 写回改它),
|
|
80
|
+
* 续跑照它读、不再由治理层按段重钳。写点两个 = {@link buildCheckpointCtx}(每一次新的持久化写都写)与 {@link withPermissionModeRewritten}(`plan_review` 写回改词的那一拍写);
|
|
81
|
+
* **不改词**的续跑腿写回传原 ctx ⇒ 记号随行。 */
|
|
82
|
+
export declare const PERMISSION_MODE_READINGS: readonly ["entry_word"];
|
|
83
|
+
export type PermissionModeReading = (typeof PERMISSION_MODE_READINGS)[number];
|
|
85
84
|
/**
|
|
86
85
|
* 一次**新的**持久化写的 ctx(提交腿 / `POST /v1/runs` 族 / leader worker)—— 写记号的唯一口。
|
|
87
86
|
*
|
|
88
|
-
* 调用方是「本进程刚按当前读法读过这份体」的写点:fresh 提交(受理门按当前读法读过 `allow`),或已经过了续跑拒臂的重放腿
|
|
89
|
-
* (`startFreshHostTurn` 把宿主的存量体交给 `POST /v1/runs` 同一条链 —— 它在那之前调过 `resolveResumeSpecOrBlocked`,没记号却带 `allow` 的体到不了这里)。
|
|
90
87
|
* 续跑腿的**写回**不经本函数:**不改词**的写回传读进来的 ctx(记号随行,不重新判 —— 在写回口重新判会把一条没记号的旧行「洗」成新行);
|
|
91
88
|
* **改词**的写回(只有 `plan_review` 的批准 / 编辑)经 {@link withPermissionModeRewritten}。两种写回落盘之前都过同一只封口 {@link sealCheckpointCtx}。
|
|
92
89
|
*
|
|
@@ -103,27 +100,27 @@ export declare function buildCheckpointCtx(fields: {
|
|
|
103
100
|
* 模式词的**第二个写者** —— `plan_review` 的批准 / 编辑把这条 run 的体词从 `plan` 写成批准的档(`resume-legs.ts` `drivePlanReview`,调用点只有那一处;
|
|
104
101
|
* `test/allow-list-reading-park-refusal.test.ts` 枚举调用点,多一处即红)。与 {@link buildCheckpointCtx} **同一条规则**:按当前读法写下的词,盖当前读法记号。
|
|
105
102
|
*
|
|
106
|
-
*
|
|
103
|
+
* 为什么记号必须随词一起写,而不是留给读的一侧去豁免:模式词问问的是「体的词是不是按当前读法写下的」,记号就是这句话的证据。改写之后体里的词是本版的 `plan_review`
|
|
107
104
|
* 刚写下的(一个人刚批准的档),它确实是 `entry_word` 读法的词;若只改体、记号缺席,重建段的同一问把它读成「7.121.x 的请求原词」,被地板钳回 `plan` ≠ 所写词 ⇒ 误拒
|
|
108
105
|
* 一条刚被批准的 run。判据侧(`stored-body-replay.ts`)**不为「plan_review 之后」另开特判臂** —— 读的一侧只有一个读法,写的一侧各自负责盖章。
|
|
109
106
|
*
|
|
110
107
|
* 为什么这不是在「洗」旧行:走到写回口的行,其**原体**已过 prepare 段的同一问(词被地板钳不变:词已是 `plan`,或本部署没有地板);原体的词会被地板钳的旧行
|
|
111
|
-
* (`acceptEdits` / `bypassPermissions` / 无词)在 prepare 段就被拒,到不了这里。入参 `ctx` 的其余位(memoryScope / 无人值守标
|
|
108
|
+
* (`acceptEdits` / `bypassPermissions` / 无词)在 prepare 段就被拒,到不了这里。入参 `ctx` 的其余位(memoryScope / 无人值守标)原样随行,只换体与模式词记号。
|
|
112
109
|
*
|
|
113
110
|
* 本模块零值依赖的闭包纪律不变(随包排空脚本经编译产物 import;`test/drain-check-local.test.ts`):本函数只用本模块内的东西。
|
|
114
111
|
*/
|
|
115
112
|
export declare function withPermissionModeRewritten(ctx: CheckpointCtx, body: TaskRequestBody): CheckpointCtx;
|
|
116
|
-
/** 行上带的是不是当前的模式词读法记号(
|
|
117
|
-
* 记号缺席或认不得 ⇒
|
|
113
|
+
/** 行上带的是不是当前的模式词读法记号(模式词问的记号那一半;另一半 —— 体的生效词被地板钳会不会变 —— 读请求设置的解析层,住在 `http/stored-body-replay.ts`)。
|
|
114
|
+
* 记号缺席或认不得 ⇒ 不是「按当前读法写下」的证据。 */
|
|
118
115
|
export declare function permissionModeReadingStated(ctx: CheckpointCtx): boolean;
|
|
119
116
|
/**
|
|
120
|
-
*
|
|
117
|
+
* 模式词问的拒答复 —— 码 `checkpoint.unsupported_version`,409(卡仍 pending 时体上的 `retriable:true` 由 {@link resumeRefusalWithCard} 追加,本铸点不带)。
|
|
121
118
|
* 句子说原因(更早的版本在每次续跑重钳运维的 AUTONOMY、没把它记进任务;本版只在提交时记一次 ⇒ 续跑会按任务提交时的原词跑)与两条出路。
|
|
122
119
|
* 🔴 形是给冻结门看的:`status: <三位数>, body: refusalBody({ errorCode: "<码>", message: "<整句双引号字面>"`,中间只许有空白。
|
|
123
120
|
*/
|
|
124
121
|
export declare function permissionModeReadingRefusal(): ResumeRefusalAnswer;
|
|
125
122
|
/**
|
|
126
|
-
*
|
|
123
|
+
* 退役请求键问:**退役的请求键**闭集 = 两张处置表之并(新提交在键闭集门 400;存体里还带着它 = 这份体是更早的写者写下的)。键住在哪张表就是它的处置格,规则全文见头注「退役请求键问」。
|
|
127
124
|
* 拒表:存体仍带它 ⇒ 续跑重放拒({@link retiredRequestKeyRefusal});加一个 ⇒ 加一行,那只函数的 switch 编译红直到给它一句拒句。今天一只:`promptProfile`(7.137.0 起换成布尔 `promptLean`;存体由 M30 起服改写)。
|
|
128
125
|
*/
|
|
129
126
|
export declare const REPLAY_REFUSED_RETIRED_KEYS: readonly ["promptProfile"];
|
|
@@ -135,7 +132,7 @@ export type RetiredRequestKey = (typeof RETIRED_REQUEST_KEYS)[number];
|
|
|
135
132
|
/** 存体顶层带的第一只**需要拒**的退役请求键(拒表序);惰性键不算,没有 ⇒ `undefined`。只看自有键(原型上的同名不算)。 */
|
|
136
133
|
export declare function retiredRequestKeyOf(body: unknown): ReplayRefusedRetiredKey | undefined;
|
|
137
134
|
/**
|
|
138
|
-
*
|
|
135
|
+
* 退役请求键问的拒答复 —— 码与落点同模式词读法拒(`checkpoint.unsupported_version`,409;卡仍 pending 时的 `retriable:true` 由 {@link resumeRefusalWithCard} 追加,本铸点不带)。
|
|
139
136
|
* 句子说键、它换成了什么、为什么不续跑,与两条出路(运维在一次性迁移的窗内重启本服务 ⇒ 起服改写存体、同一请求可再发;否则作为新任务重提,仍停驻的先取消)。不回显值。
|
|
140
137
|
* 🔴 形是给冻结门看的:`status: <三位数>, body: refusalBody({ errorCode: "<码>", message: <整句双引号字面 或 一只模板串>`,中间只许有空白(模板串形冻结的是骨架,`${…}` 折成一个洞)。
|
|
141
138
|
* **窗的日期不手写**:`rewriteWindowEnd` 由调用方交 —— 判据(`stored-body-replay.ts`)按「退役键 → 改写它的迁移」那张表读登记表该行的 `removableAfter`,窗只写在登记表一处;
|
|
@@ -143,32 +140,23 @@ export declare function retiredRequestKeyOf(body: unknown): ReplayRefusedRetired
|
|
|
143
140
|
* 删法见登记表 M30 的 `removal`(唯一来源)。
|
|
144
141
|
*/
|
|
145
142
|
export declare function retiredRequestKeyRefusal(key: ReplayRefusedRetiredKey, rewriteWindowEnd: string): ResumeRefusalAnswer;
|
|
146
|
-
/**
|
|
147
|
-
* 本行能否被按当前读法重放:体里 `allow` 在生效而行上的记号不是当前这一个词 ⇒ **不能**(`true` = 拒)。
|
|
148
|
-
* 记号缺席、是旧词(`"statement"`)或认不得(手改 / 将来的写者)⇒ 同样拒:只有当前这个词是「按当前读法写下」的证据。
|
|
149
|
-
*/
|
|
150
|
-
export declare function allowListReadingUnstated(ctx: CheckpointCtx): boolean;
|
|
151
|
-
/** 被拒的行是哪一代写的(只在 {@link allowListReadingUnstated} 为真时有意义):记号是 `"statement"` ⇒ 表态时代;其余(缺席 / 认不得)⇒ 名单时代。 */
|
|
152
|
-
export declare function allowListReadingEraOf(ctx: CheckpointCtx): AllowListReadingEra;
|
|
153
|
-
/**
|
|
154
|
-
* 拒的答复 —— 码与落点照「退役 mode-seed 行」的先例(`checkpoint.unsupported_version`,409;卡仍 pending 时的 `retriable:true` 由 {@link resumeRefusalWithCard} 追加,本铸点不带)。
|
|
155
|
-
* 拒在认领之前,所以没有 `taskId`(行没抢到就不造键)。句子按这一行是哪一代写的分两句(闭集穷举,加一代 ⇒ 编译红):说原因(这条任务停在哪种读法上、
|
|
156
|
-
* 照当前读法续跑会放宽什么)与出路(作为新任务重提,仍停驻的先取消)。
|
|
157
|
-
*
|
|
158
|
-
* 🔴 形是给冻结门看的(`api-error-text-freeze` 的 resume 家族收集器):`status: <三位数>, body: refusalBody({ errorCode: "<码>", message: "<整句双引号字面>"`,中间只许有空白。
|
|
159
|
-
*/
|
|
160
|
-
export declare function allowListReadingRefusal(era: AllowListReadingEra): ResumeRefusalAnswer;
|
|
161
143
|
/**
|
|
162
144
|
* 一条停驻行的持久化体在本版上**不能**重放时,是哪一条规则拒的(闭集;加一条 ⇒ {@link storedBodyReplayAnswer} 的 switch 编译红)。
|
|
163
145
|
* 答 `checkpoint.unsupported_version` 的三臂随带这一行的写者版本(续跑上下文的 `writerVersion`,缺席 = 本版之前写下的行)—— 那一码的两版本键由它铸({@link buildCheckpointVersionKeys})。
|
|
164
146
|
*/
|
|
165
|
-
export type StoredBodyReplayRefusal =
|
|
147
|
+
export type StoredBodyReplayRefusal =
|
|
148
|
+
/** 体里带非空 `settings.permissions.allow`、写者版本证不出 ≥ {@link ALLOW_LAYER_READING_SINCE}(顶注「allow 读法问」)。 */
|
|
149
|
+
{
|
|
166
150
|
readonly kind: "allow_list_reading";
|
|
167
|
-
readonly era: AllowListReadingEra;
|
|
168
151
|
readonly writerVersion?: string;
|
|
169
152
|
} | {
|
|
170
153
|
readonly kind: "inert_tool_list";
|
|
171
154
|
readonly entry: InertToolListEntry;
|
|
155
|
+
}
|
|
156
|
+
/** 存体 `settings.env` 带凭据条目、一次性迁移 M38 的剥键窗已关:`refusal` = 提交腿那只 400(`request.env_credential_refused`)的码、句子与机读位(由预判用同一只判据铸),答复折成 409 `resume_blocked_by_policy`。 */
|
|
157
|
+
| {
|
|
158
|
+
readonly kind: "settings_env_credential";
|
|
159
|
+
readonly refusal: Refusal;
|
|
172
160
|
} | {
|
|
173
161
|
readonly kind: "permission_mode_reading";
|
|
174
162
|
readonly stored: PermissionMode | undefined;
|
|
@@ -231,12 +219,12 @@ export declare function isResumeBlockedByPolicy(answer: {
|
|
|
231
219
|
*/
|
|
232
220
|
export declare function resumeRefusalWithCard(answer: ResumeRefusalAnswer, cardPending: boolean): ResumeRefusalAnswer;
|
|
233
221
|
/**
|
|
234
|
-
* `stored-body-replay.ts` `storedBodyReplayRefusal` 的**日志字段**(三处问点同一形,各自只再加坐标键 `sessionId` / `taskId`):`kind`
|
|
222
|
+
* `stored-body-replay.ts` `storedBodyReplayRefusal` 的**日志字段**(三处问点同一形,各自只再加坐标键 `sessionId` / `taskId`):`kind` 判别,技能臂带 `layer`、退役键臂带 `key`、allow 读法臂带 `writerVersion`(有才在),`note` 一句出路。
|
|
235
223
|
* 事件名三个(问点各一:`resume_refused_stored_body` / `steer_wake_park_refused_stored_body` / `deny_sweep_stored_body_skipped`),字段形只有这一只。
|
|
236
224
|
*/
|
|
237
225
|
export declare function storedBodyReplayLogFields(refusal: StoredBodyReplayRefusal): {
|
|
238
226
|
kind: StoredBodyReplayRefusal["kind"];
|
|
239
|
-
|
|
227
|
+
writerVersion?: string;
|
|
240
228
|
layer?: InertToolListEntry["layer"];
|
|
241
229
|
storedMode?: PermissionMode | null;
|
|
242
230
|
floor?: PermissionMode;
|
|
@@ -244,13 +232,13 @@ export declare function storedBodyReplayLogFields(refusal: StoredBodyReplayRefus
|
|
|
244
232
|
note: string;
|
|
245
233
|
};
|
|
246
234
|
/**
|
|
247
|
-
* `stored-body-replay.ts` `storedBodyReplayRefusal` 的答复:每条规则一只既有铸点(allow
|
|
235
|
+
* `stored-body-replay.ts` `storedBodyReplayRefusal` 的答复:每条规则一只既有铸点(allow 读法 ⇒ {@link allowListReadingRefusal};模式词记号 ⇒ {@link permissionModeReadingRefusal};
|
|
248
236
|
* 退役请求键 ⇒ {@link retiredRequestKeyRefusal};这三只答 `checkpoint.unsupported_version`,体按那一码的键律补两版本键,`readerVersion` = 调用方传的本进程服务版本;工具名清单 ⇒ {@link resumeBlockedByPolicyAnswer},与提交腿的 400
|
|
249
237
|
* (该层的拒码:`request.field_invalid` / `config.agent.unknown_tool` / `config.tool_face_control`)同码同句 —— 体上只有这一个问题时;存量体同时还踩中 `resolveSpec` 更早的拒〔三桶超帽 / 托管姿态〕时,提交侧答更早那条、续跑侧答本句,两边都是拒,指路不同)。
|
|
250
238
|
*
|
|
251
239
|
* 🔴 `cardPending` —— **调用方交出的事实**:这一次拒的时候,有没有一张待批卡仍在等。`retriable:true` 说的恰是「卡仍 pending」,所以它只在卡在时在场(经
|
|
252
240
|
* {@link resumeRefusalWithCard} 一处写):续跑入口(`/decide` · `/resume` · `/wake` · plan_review · workflow 决定的新一跑,五个问点里除下面这一个之外全部)传 `true`;
|
|
253
|
-
* 终态 run 的 `POST /v1/runs/:id/steer` 在**铸唤醒卡之前**就拒,没有卡也没铸卡 ⇒ 传 `false`,体上不带 `retriable`(
|
|
241
|
+
* 终态 run 的 `POST /v1/runs/:id/steer` 在**铸唤醒卡之前**就拒,没有卡也没铸卡 ⇒ 传 `false`,体上不带 `retriable`(每条臂同一条律;其余键两种处境逐字相同 —— 同判同答)。
|
|
254
242
|
* 没有默认值:每个调用点必须说出这件事实。
|
|
255
243
|
*/
|
|
256
244
|
export declare function storedBodyReplayAnswer(refusal: StoredBodyReplayRefusal, readerVersion: string, cardPending: boolean): ResumeRefusalAnswer;
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { refusalBody } from "./refusal-body.js";
|
|
2
|
-
export const
|
|
3
|
-
export const PERMISSION_MODE_READINGS = ["entry_word"];
|
|
4
|
-
export const ALLOW_LIST_READING_ERAS = ["list", "statement"];
|
|
2
|
+
export const ALLOW_LAYER_READING_SINCE = "7.117.0";
|
|
5
3
|
export function bodyCarriesAllowList(body) {
|
|
6
4
|
const settings = body?.settings;
|
|
7
5
|
if (settings === null || typeof settings !== "object" || Array.isArray(settings))
|
|
@@ -12,6 +10,33 @@ export function bodyCarriesAllowList(body) {
|
|
|
12
10
|
const allow = permissions["allow"];
|
|
13
11
|
return Array.isArray(allow) && allow.length > 0;
|
|
14
12
|
}
|
|
13
|
+
const SEMVER = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
14
|
+
function readVersion(v) {
|
|
15
|
+
const m = SEMVER.exec(v);
|
|
16
|
+
return m === null ? undefined : { core: [Number(m[1]), Number(m[2]), Number(m[3])], pre: m[4] !== undefined };
|
|
17
|
+
}
|
|
18
|
+
export function writerReadsAllowLayer(writerVersion) {
|
|
19
|
+
if (typeof writerVersion !== "string")
|
|
20
|
+
return false;
|
|
21
|
+
const writer = readVersion(writerVersion);
|
|
22
|
+
const since = readVersion(ALLOW_LAYER_READING_SINCE);
|
|
23
|
+
if (writer === undefined)
|
|
24
|
+
return false;
|
|
25
|
+
for (let i = 0; i < 3; i++)
|
|
26
|
+
if (writer.core[i] !== since.core[i])
|
|
27
|
+
return writer.core[i] > since.core[i];
|
|
28
|
+
return !writer.pre;
|
|
29
|
+
}
|
|
30
|
+
export function allowListWriterUnproven(ctx) {
|
|
31
|
+
return bodyCarriesAllowList(ctx.body) && !writerReadsAllowLayer(ctx.writerVersion);
|
|
32
|
+
}
|
|
33
|
+
export function allowListReadingRefusal() {
|
|
34
|
+
return {
|
|
35
|
+
status: 409,
|
|
36
|
+
body: refusalBody({ errorCode: "checkpoint.unsupported_version", message: "this task's stored request carries settings.permissions.allow and was written by a server version that is earlier than 7.117.0 or that did not record its version (versions before 7.124.0 did not), so this server cannot tell how that list was meant to be read: 7.114.0 and earlier read it as a whitelist (every tool not on it was refused) and 7.115.0 to 7.116.x as a statement that answered only the question nobody else had answered, while this version hands it to the engine's allow layer, where each entry is a standing yes for the calls it covers, so continuing could give the task more tools or fewer questions than it was submitted with. Nothing was decided and nothing was resumed, and retrying will be refused the same way: submit the work again as a new task, and if this task is still suspended cancel it first (POST /v1/runs/:id/cancel)." }),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export const PERMISSION_MODE_READINGS = ["entry_word"];
|
|
15
40
|
export function buildCheckpointCtx(fields, sealer, sessionId) {
|
|
16
41
|
const ctx = {
|
|
17
42
|
body: fields.body,
|
|
@@ -19,7 +44,6 @@ export function buildCheckpointCtx(fields, sealer, sessionId) {
|
|
|
19
44
|
...(fields.memoryScope !== undefined ? { memoryScope: fields.memoryScope } : {}),
|
|
20
45
|
...(fields.unattendedLeg === true ? { unattendedLeg: true } : {}),
|
|
21
46
|
...(fields.promptScreened === true ? { promptScreened: true } : {}),
|
|
22
|
-
...(bodyCarriesAllowList(fields.body) ? { permissionsAllowReading: "allow_layer" } : {}),
|
|
23
47
|
permissionModeReading: "entry_word",
|
|
24
48
|
};
|
|
25
49
|
return sealCheckpointCtx(ctx, sealer, sessionId);
|
|
@@ -64,40 +88,6 @@ export function retiredRequestKeyRefusal(key, rewriteWindowEnd) {
|
|
|
64
88
|
}
|
|
65
89
|
}
|
|
66
90
|
}
|
|
67
|
-
export function allowListReadingUnstated(ctx) {
|
|
68
|
-
if (!bodyCarriesAllowList(ctx.body))
|
|
69
|
-
return false;
|
|
70
|
-
const reading = ctx.permissionsAllowReading;
|
|
71
|
-
return !(typeof reading === "string" && PERMISSIONS_ALLOW_READINGS.includes(reading));
|
|
72
|
-
}
|
|
73
|
-
export function allowListReadingEraOf(ctx) {
|
|
74
|
-
const reading = ctx.permissionsAllowReading;
|
|
75
|
-
return reading === "statement" ? "statement" : "list";
|
|
76
|
-
}
|
|
77
|
-
export function allowListReadingRefusal(era) {
|
|
78
|
-
switch (era) {
|
|
79
|
-
case "list":
|
|
80
|
-
return {
|
|
81
|
-
status: 409,
|
|
82
|
-
body: refusalBody({
|
|
83
|
-
errorCode: "checkpoint.unsupported_version",
|
|
84
|
-
message: "this task was suspended by an earlier server version that did not record how it read settings.permissions.allow (7.114.0 and earlier read it as a whitelist: every tool not on the list was refused); this version hands that list to the engine's allow layer, where each entry is a standing yes for the calls it covers, so continuing would give the task more tools than it was submitted with. Nothing was decided and nothing was resumed, and retrying will be refused the same way: submit the work again as a new task, and if this task is still suspended cancel it first (POST /v1/runs/:id/cancel). To allow only certain tools, use the session rules' toolAllow (PUT /v1/sessions/:id/policy) or the request's excludeTools.",
|
|
85
|
-
}),
|
|
86
|
-
};
|
|
87
|
-
case "statement":
|
|
88
|
-
return {
|
|
89
|
-
status: 409,
|
|
90
|
-
body: refusalBody({
|
|
91
|
-
errorCode: "checkpoint.unsupported_version",
|
|
92
|
-
message: "this task was suspended by an earlier server version (7.115.0 to 7.116.x) that read settings.permissions.allow as a statement that the named tools are allowed, which answered only the question nobody else had answered and never cleared an ordinary question such as a file write or a shell command; this version hands that list to the engine's allow layer, where an entry also clears those ordinary questions, so continuing would run calls without asking that the task was submitted to ask about. Nothing was decided and nothing was resumed, and retrying will be refused the same way: submit the work again as a new task, and if this task is still suspended cancel it first (POST /v1/runs/:id/cancel).",
|
|
93
|
-
}),
|
|
94
|
-
};
|
|
95
|
-
default: {
|
|
96
|
-
const unhandled = era;
|
|
97
|
-
throw new Error(`allow-list reading era ${String(unhandled)} has no refusal sentence`);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
91
|
export function buildCheckpointVersionKeys(writerVersion, readerVersion) {
|
|
102
92
|
return writerVersion !== undefined ? { writerVersion, readerVersion } : {};
|
|
103
93
|
}
|
|
@@ -116,9 +106,11 @@ export function resumeRefusalWithCard(answer, cardPending) {
|
|
|
116
106
|
export function storedBodyReplayLogFields(refusal) {
|
|
117
107
|
switch (refusal.kind) {
|
|
118
108
|
case "allow_list_reading":
|
|
119
|
-
return { kind: refusal.kind,
|
|
109
|
+
return { kind: refusal.kind, ...(refusal.writerVersion !== undefined ? { writerVersion: refusal.writerVersion } : {}), note: "this session's stored request carries settings.permissions.allow and its writer version does not show it was written under the allow-layer reading (7.117.0 and later; versions before 7.124.0 recorded no writer version); it is not replayed under the current reading — the task stays suspended until someone cancels it" };
|
|
120
110
|
case "inert_tool_list":
|
|
121
111
|
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" };
|
|
112
|
+
case "settings_env_credential":
|
|
113
|
+
return { kind: refusal.kind, note: "this session's stored request carries credentials in settings.env (a credential variable name of this engine, or a value shaped like a secret) and the one-time window that dropped them on resume has closed; it is not replayed — the task stays suspended until someone cancels it and resubmits with the credentials moved into the engine's environment" };
|
|
122
114
|
case "permission_mode_reading":
|
|
123
115
|
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" };
|
|
124
116
|
case "retired_request_key":
|
|
@@ -135,11 +127,13 @@ export function storedBodyReplayAnswer(refusal, readerVersion, cardPending) {
|
|
|
135
127
|
function storedBodyReplayArmAnswer(refusal, readerVersion) {
|
|
136
128
|
switch (refusal.kind) {
|
|
137
129
|
case "allow_list_reading": {
|
|
138
|
-
const answer = allowListReadingRefusal(
|
|
130
|
+
const answer = allowListReadingRefusal();
|
|
139
131
|
return { status: answer.status, body: { ...answer.body, ...buildCheckpointVersionKeys(refusal.writerVersion, readerVersion) } };
|
|
140
132
|
}
|
|
141
133
|
case "inert_tool_list":
|
|
142
134
|
return resumeBlockedByPolicyAnswer(refusal.entry.extra === undefined ? { errorCode: refusal.entry.code, message: refusal.entry.message } : { errorCode: refusal.entry.code, message: refusal.entry.message, facts: refusal.entry.extra });
|
|
135
|
+
case "settings_env_credential":
|
|
136
|
+
return resumeBlockedByPolicyAnswer(refusal.refusal);
|
|
143
137
|
case "permission_mode_reading": {
|
|
144
138
|
const answer = permissionModeReadingRefusal();
|
|
145
139
|
return { status: answer.status, body: { ...answer.body, ...buildCheckpointVersionKeys(refusal.writerVersion, readerVersion) } };
|
package/dist/http/dispatch.js
CHANGED
|
@@ -11,6 +11,7 @@ import { ENGINE_SIGNAL_KEY, buildEngineSignal, fleetMembershipKeys, healthConfig
|
|
|
11
11
|
import { buildHealthSelfReport } from "./health-self-report.js";
|
|
12
12
|
import { deploymentModPackages as deploymentModPackagesFact } from "../capability-facts.js";
|
|
13
13
|
import { actsForDeployment, admitRunIdentity, authorized, systemFor, gatedPrincipal, sendPrincipalRefusal, sendUnauthorized, traceTokenPresented, verifiedIdentitySource, hasServiceAuth, devOpenDeployment } from "./principal-gate.js";
|
|
14
|
+
import { inflightTotal } from "../fleet/drain-entry.js";
|
|
14
15
|
const PROCESS_STARTED_AT_MS = Date.now() - Math.round(process.uptime() * 1000);
|
|
15
16
|
export function readCredentialOk(req, config) {
|
|
16
17
|
if (!hasServiceAuth(config))
|
|
@@ -137,10 +138,25 @@ export function createDispatch(ctx) {
|
|
|
137
138
|
status: "ok",
|
|
138
139
|
...(typeof deps.capabilities?.version === "string" ? { version: deps.capabilities.version } : {}),
|
|
139
140
|
...healthDrainingKeys(signal),
|
|
140
|
-
...(
|
|
141
|
+
...(() => {
|
|
142
|
+
const breakdown = deps.drainState?.inflightBreakdown?.();
|
|
143
|
+
return breakdown ? { inflight: inflightTotal(breakdown), inflightBreakdown: breakdown } : {};
|
|
144
|
+
})(),
|
|
141
145
|
...(() => {
|
|
142
146
|
const lease = deps.drainState?.engineLease?.();
|
|
143
|
-
|
|
147
|
+
if (!lease)
|
|
148
|
+
return {};
|
|
149
|
+
const fa = lease.firstAttach;
|
|
150
|
+
const ho = lease.handover;
|
|
151
|
+
return {
|
|
152
|
+
engineLease: {
|
|
153
|
+
lingerMs: lease.lingerMs,
|
|
154
|
+
tickMs: lease.tickMs,
|
|
155
|
+
lane: lease.lane,
|
|
156
|
+
...(fa ? { firstAttach: { windowMs: fa.windowMs, since: fa.since, attachedAt: fa.attachedAt } } : {}),
|
|
157
|
+
...(ho ? { handover: { since: ho.since, reason: ho.reason, lingerMs: ho.lingerMs, backgroundShells: ho.backgroundShells } } : {}),
|
|
158
|
+
},
|
|
159
|
+
};
|
|
144
160
|
})(),
|
|
145
161
|
...(deps.storePosture?.degradedReason !== undefined ? { durable: false, storeDegraded: true } : {}),
|
|
146
162
|
...healthReadinessKeys(signal.verdict),
|
|
@@ -2,6 +2,7 @@ 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
4
|
import type { RunIdentity } from "../identity-source.js";
|
|
5
|
+
import type { RunSlot } from "./run-concurrency-cap.js";
|
|
5
6
|
export interface DurableRunLegArgs {
|
|
6
7
|
/** `prepareSpec` 的产物,或内部车道按同一条 `resolveSpec` 装配出来的等价形。 */
|
|
7
8
|
prepared: PreparedTaskSubmission;
|
|
@@ -27,6 +28,10 @@ export interface DurableRunLegArgs {
|
|
|
27
28
|
/** `/decide` 第三条车道的 fresh 投递腿交来的那一件决定投递(带着的决定 + 起跑之前落行的那一笔;语义与 TRUSTED 纪律的属主 =
|
|
28
29
|
* `route-ctx.ts` 的 {@link WorkflowDecisionDelivery} 顶注)。缺席 ⇒ 只摊本会话已受理的决定行。 */
|
|
29
30
|
workflowDecision?: WorkflowDecisionDelivery;
|
|
31
|
+
/** 提交门占着的**并发帽席位**(`http/run-concurrency-cap.ts`):本腿在 `runInBackground` 把这条 run 登记进 `inflightRuns` 的那一拍(它在返回前同步登记)就地放掉 ——
|
|
32
|
+
* 与 `POST /v1/tasks` 两口同形,在飞集里的这一条不再叠一枚席位。落点拒 / 续跑输入拒 / 409 / 抛 等没走到登记的出口不放,由提交门的 `finally` 兜底(`release` 幂等)。
|
|
33
|
+
* 缺席 = 没有帽可放(`/decide` 第三条车道〔延续,不判帽〕、帽关着的部署)。 */
|
|
34
|
+
runSlot?: RunSlot;
|
|
30
35
|
}
|
|
31
36
|
/**
|
|
32
37
|
* 本腿的结局:一份收据,或「这次提交的一把幂等钥匙已经指向一条行」(店的原子赢或观察的**观察**臂 —— 本腿不碰
|
|
@@ -99,6 +99,7 @@ export async function mintAndDriveDurableRun(ctx, runStore, args) {
|
|
|
99
99
|
executionLane: args.prepared.execution.lane,
|
|
100
100
|
}
|
|
101
101
|
: undefined, deps.checkpointStore, args.prepared.engineNotices, trustedInternals, deps.userInputLedger, args.prepared.acceptance, createSessionWorkspaceRecorder(sessionWorkspaceStoreOf(deps.sessionStorage), args.prepared.legFacts?.sessionWitness), args.prepared.legFacts?.skills));
|
|
102
|
+
args.runSlot?.release();
|
|
102
103
|
return { status: 202, body: { taskId, sessionId, status: "running", ...(args.prepared.warnings !== undefined ? { warnings: args.prepared.warnings } : {}) } };
|
|
103
104
|
}
|
|
104
105
|
//# sourceMappingURL=durable-run-leg.js.map
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
* 在场而与行头不是同一位住客(化身 ∧ 属主,写口同一只判官 `sameOccupant`)⇒ 同 404(他人在门与解析之间删掉并同 id 重登记,或同一化身的属主变了 ——
|
|
13
13
|
* local M10 认领 / identical 重戳 / SQL 导入提交点改属主 —— 判到新住客的车道就是错的);local 格是 `forking`
|
|
14
14
|
* ⇒ 409 `conflict.fork_in_progress`;读故障抛(不吞成 absent)。解析器不建行、不铸根。
|
|
15
|
+
* 随后(同一步,就在那一读之后):这只根会话 id 在本进程被删过、而那一读的住客不是删前的属主 ⇒ 409 `conflict.session_id_retired`
|
|
16
|
+
* (表与规则 `deleted-session-ids.ts`,这里是它唯一的读点;店不带执行席 ⇒ fresh 判门判过的那一读,continuation 判不出 ⇒ 表里有就拒)。
|
|
15
17
|
* ② 定车道:`mirror` ⇒ 409 `conflict.session_mirror`(体带 `forkPath`);`writer(L)` 而 L 不在本部署的车道表 ⇒ 409 `execution_lane.not_served{boundLane}`;absent ⇒ 表首。
|
|
16
18
|
* ③ 授权:主体的执行车道裁定(`gateExecutionLane`,判据与码同 `runtime-caps-resolver.ts`);服务形不判。
|
|
17
19
|
* ④ 只 fresh:设备准入链(体 `deviceId` 只在 device 车道收;准入链三步 + 首绑目标三读,全读;判的是步 ① 那一读)。
|
|
@@ -108,6 +110,8 @@ export declare function resolveExecutionContext(deps: ExecutionContextDeps, entr
|
|
|
108
110
|
readonly root: string;
|
|
109
111
|
}>): Promise<RootedExecutionContext>;
|
|
110
112
|
export declare function resolveExecutionContext(deps: ExecutionContextDeps, entry: ExecutionEntry): Promise<ExecutionContext>;
|
|
113
|
+
/** 步 ① 之后那一判的拒句(409 `conflict.session_id_retired`;不回显 id / 属主)。续跑家族把它包进 `resume_blocked_by_policy` 的句子里答。 */
|
|
114
|
+
export declare const SESSION_ID_RETIRED_MESSAGE = "this session id was deleted on this server while a different owner held it, so this server will not run it for you \u2014 start the session under a new id";
|
|
111
115
|
/** 拒体里「继续在本处执行」的下一步路径(fork 口)—— 镜像拒体的 `forkPath` 唯一铸法(执行面与会话行写口 `PATCH /v1/sessions/:id` 同读)。 */
|
|
112
116
|
export declare function forkPathOf(root: string): string;
|
|
113
117
|
/** 解析器的拒是不是「会话不在」(停驻赎回腿把它答成自己既有的 `decide.not_parked`;判据只在这里认那只答复的码)。 */
|
|
@@ -6,6 +6,7 @@ import { sameOccupant } from "../execution-placement.js";
|
|
|
6
6
|
import { deployedExecutionLanes } from "../execution-lane-caps.js";
|
|
7
7
|
import { gateExecutionLane } from "../runtime-caps-resolver.js";
|
|
8
8
|
import { releaseClaimedRun } from "./claimed-run.js";
|
|
9
|
+
import { sessionIdRetiredFor } from "../deleted-session-ids.js";
|
|
9
10
|
import { refusalBody } from "./refusal-body.js";
|
|
10
11
|
export async function resolveExecutionContext(deps, entry) {
|
|
11
12
|
const lanes = deployedExecutionLanes(deps.config);
|
|
@@ -16,6 +17,8 @@ export async function resolveExecutionContext(deps, entry) {
|
|
|
16
17
|
case "continuation": {
|
|
17
18
|
const seat = deps.sessionStorage?.executionPlacement;
|
|
18
19
|
const reading = seat === undefined ? undefined : await readRow(seat, entry.root, entry.kind === "fresh" ? entry.judged : undefined);
|
|
20
|
+
if (sessionIdRetiredFor(entry.root, servedOwnerOf(entry, reading), deps.config))
|
|
21
|
+
throw createCodedHttpError(409, "conflict.session_id_retired", SESSION_ID_RETIRED_MESSAGE);
|
|
19
22
|
const { lane, placement } = laneOf(entry.root, reading?.cell ?? { role: "absent" }, lanes);
|
|
20
23
|
gateExecutionLane(await deps.executionRuling?.(entry.principal), lane, deps.logger);
|
|
21
24
|
const ctx = { kind: entry.kind, root: entry.root, occupant: reading?.occupant, placement, lane };
|
|
@@ -30,6 +33,12 @@ export async function resolveExecutionContext(deps, entry) {
|
|
|
30
33
|
}
|
|
31
34
|
}
|
|
32
35
|
}
|
|
36
|
+
export const SESSION_ID_RETIRED_MESSAGE = "this session id was deleted on this server while a different owner held it, so this server will not run it for you — start the session under a new id";
|
|
37
|
+
function servedOwnerOf(entry, reading) {
|
|
38
|
+
if (reading !== undefined)
|
|
39
|
+
return reading.occupant.owner;
|
|
40
|
+
return entry.kind === "fresh" ? entry.judged?.owner : undefined;
|
|
41
|
+
}
|
|
33
42
|
async function readRow(seat, root, judged) {
|
|
34
43
|
const reading = await seat.read(root);
|
|
35
44
|
if (reading === undefined || (judged !== undefined && !sameOccupant(judged, reading.occupant)))
|
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
* `service_token` 臂读的正是它),所以 `required` 与 `kinds` 是同一次求值的两个投影,不是两个来源;
|
|
13
13
|
* · `auth.identityAttach` = kinds 里有没有**带调用方身份**的一类({@link carriesCallerIdentity},穷举):`service_token` 认的是系统
|
|
14
14
|
* (`systemFor` 回系统名或 null),不是人;
|
|
15
|
+
* · `auth.serviceTokenActsForDeployment` = 出示 service 凭据、不报主体的调用方在这台部署上代不代部署本人 —— `required`(同一次 kinds 求值的 `service_token` 词)
|
|
16
|
+
* ∧ 门读那一格声明的同一只读法 `serviceTokenDeclaredActsForDeployment`(`actsForDeployment` 的合取项,`principal-gate.ts`)。没配 service 凭据 ⇒ `false`(那一臂够不着);
|
|
17
|
+
* 缺省部署 ⇒ 与 `required` 同值。运维聚合口的 401 operator 句指的就是这一位;
|
|
15
18
|
* · `operator` = 能力事实 `operatorLane`(operator 面族的 501 门读的同一只;名单本身不上 wire);
|
|
16
19
|
* · `center.issuer` = 鉴权桥 issuer 的唯一取值 `authBridgeIssuerOf`(装配 `boot/stage-09-leader.ts` 与 caps `centerWiring.issuer` 同读);
|
|
17
20
|
* · `center.webBaseUrl` = 运维旋钮 `SEMA_WEB_ADMIN_WEB_URL`(`config.webAdmin.webBaseUrl`,接了中心才挂;起服时已判成固定基址);
|
|
@@ -49,6 +52,7 @@ export interface HealthSelfReport {
|
|
|
49
52
|
readonly required: boolean;
|
|
50
53
|
readonly kinds: readonly IdentitySource[];
|
|
51
54
|
readonly identityAttach: IdentityAttach;
|
|
55
|
+
readonly serviceTokenActsForDeployment: boolean;
|
|
52
56
|
};
|
|
53
57
|
readonly operator: OperatorPresence;
|
|
54
58
|
readonly center: {
|
|
@@ -58,8 +62,8 @@ export interface HealthSelfReport {
|
|
|
58
62
|
};
|
|
59
63
|
}
|
|
60
64
|
/**
|
|
61
|
-
* 三键的**唯一铸点**(`build*`:纯数据)。只读装配本身:`auth`
|
|
62
|
-
*
|
|
65
|
+
* 三键的**唯一铸点**(`build*`:纯数据)。只读装配本身:`auth` 四位都从一次 `wiredIdentitySources` 求值投出(`required` = 其中有 `service_token`;
|
|
66
|
+
* `serviceTokenActsForDeployment` = `required` ∧ 门读的那一格声明),不收调用方递进来的第二份布尔 —— 一个事实一次求值。
|
|
63
67
|
*/
|
|
64
68
|
export declare function buildHealthSelfReport(deps: Pick<FlatServiceDeps, "config" | "webAdminJwtVerifier" | "sessionStorage" | "runStore">): HealthSelfReport;
|
|
65
69
|
//# sourceMappingURL=health-self-report.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { wiredIdentitySources } from "./principal-gate.js";
|
|
1
|
+
import { serviceTokenDeclaredActsForDeployment, wiredIdentitySources } from "./principal-gate.js";
|
|
2
2
|
import { operatorLane, sessionList } from "../capability-facts.js";
|
|
3
3
|
import { authBridgeIssuerOf } from "../auth-bridge.js";
|
|
4
4
|
import { centerLaneConfigured } from "../web-admin-client/center-request.js";
|
|
@@ -26,8 +26,9 @@ export function buildHealthSelfReport(deps) {
|
|
|
26
26
|
const issuer = authBridgeIssuerOf(config)?.issuer;
|
|
27
27
|
const webBaseUrl = config.webAdmin?.webBaseUrl;
|
|
28
28
|
const sessionsVisible = centerLaneConfigured(config) && config.fleetAdvertiseAddress !== undefined && bridgeWired && sessionList(deps).available ? (config.requirePrincipal ? true : "unknown") : false;
|
|
29
|
+
const required = kinds.includes("service_token");
|
|
29
30
|
return {
|
|
30
|
-
auth: { required
|
|
31
|
+
auth: { required, kinds, identityAttach: kinds.some(carriesCallerIdentity) ? "available" : "unavailable", serviceTokenActsForDeployment: required && serviceTokenDeclaredActsForDeployment(config) },
|
|
31
32
|
operator: operatorLane(deps).available ? "present" : "absent",
|
|
32
33
|
center: {
|
|
33
34
|
...(issuer !== undefined ? { issuer: buildDisplaySafeUrl(issuer) } : {}),
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* ① core 的**本口专属**码(闭集穷举 `switch`,见 {@link sentCoreCode})—— 码与状态两面同;文案按受众(下一节,一条规则);
|
|
13
13
|
* ② **店形拒**两码 `memory.target_outside_store`(core 7.31.1 [ref])/ `memory.scope_home_not_directory`(core 7.44.0 [ref])—— 跨面 store 状态码,409、码原样
|
|
14
14
|
* (判据 `memory-store-refusal.ts` 一只;运维行 `memory_store_form_refused { code, path?, form? }` 两受众同一只铸点,路径只在那里);
|
|
15
|
-
* ③ `ControlPlaneCorruptError` —— typed 500 `internal.memory_control_plane_corrupt`(fail-closed
|
|
15
|
+
* ③ `ControlPlaneCorruptError` —— typed 500 `internal.memory_control_plane_corrupt`(fail-closed 信号,一码两义;映射本体在 `memory-control-plane-corrupt-reply.ts` 那一只,导出导入 / 外源 / 整理 / 合规各口同调);
|
|
16
16
|
* 其余 ⇒ `false`(未分类,调用方发它自己那句 500 且**不回显**内部文本)。
|
|
17
17
|
*
|
|
18
18
|
* ## 文案按受众分(码与状态不分)—— **一条规则,三层同施,不按码挑**(F9,7.108.0 合并复审 opus 腿 O-9)
|