@sema-agent/server 7.150.0 → 7.151.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 +185 -0
- package/USAGE.md +53 -25
- package/deploy/sema-up/README.md +7 -1
- package/deploy/sema-up/chart/Chart.yaml +1 -1
- package/deploy/sema-up/chart/templates/NOTES.txt +5 -0
- package/deploy/sema-up/chart/templates/_helpers.tpl +15 -16
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -3
- package/deploy/sema-up/chart/templates/server.yaml +5 -3
- package/deploy/sema-up/chart/values-full-single.yaml +3 -1
- package/deploy/sema-up/chart/values.yaml +8 -1
- package/deploy/sema-up/cluster-up.sh +1 -0
- package/deploy/sema-up/kube-up.sh +1 -1
- package/deploy/sema-up/lib/flagshape.sh +1 -1
- package/deploy/sema-up/lib/helm-values-cluster.py +2 -0
- package/deploy/sema-up/lib/helm-values-kube.py +2 -0
- package/dist/adoption/import.js +3 -3
- package/dist/approval-ask-machine.d.ts +1 -1
- package/dist/approval-card.d.ts +2 -2
- package/dist/approval-gate-currency.d.ts +1 -1
- package/dist/auth-bridge.d.ts +20 -0
- package/dist/auth-bridge.js +9 -0
- package/dist/background-session-reap.d.ts +1 -1
- package/dist/bake-runner/main.d.ts +4 -2
- package/dist/bind-host.d.ts +2 -3
- package/dist/bind-host.js +2 -4
- package/dist/boot/budget-tracing.js +1 -1
- package/dist/boot/engine-lease.d.ts +5 -0
- package/dist/boot/engine-lease.js +1 -0
- package/dist/boot/execution-env.d.ts +8 -14
- package/dist/boot/execution-env.js +54 -17
- package/dist/boot/execution-lane.js +32 -5
- package/dist/boot/late-binds.d.ts +8 -4
- package/dist/boot/late-binds.js +7 -1
- package/dist/boot/memory-consolidation.d.ts +3 -2
- package/dist/boot/memory-consolidation.js +6 -6
- package/dist/boot/reapers.d.ts +5 -0
- package/dist/boot/reapers.js +12 -1
- package/dist/boot/resolve-spec.d.ts +3 -3
- package/dist/boot/resolve-spec.js +31 -22
- package/dist/boot/runner-deps.d.ts +9 -2
- package/dist/boot/runner-deps.js +3 -3
- package/dist/boot/session-age-out.d.ts +36 -0
- package/dist/boot/session-age-out.js +101 -0
- package/dist/boot/session-faces.d.ts +5 -14
- package/dist/boot/session-faces.js +9 -5
- package/dist/boot/stage-01-config.js +2 -0
- package/dist/boot/stage-05-execution-env.d.ts +5 -3
- package/dist/boot/stage-05-execution-env.js +2 -2
- package/dist/boot/stage-06-runners.d.ts +7 -4
- package/dist/boot/stage-06-runners.js +15 -6
- package/dist/boot/stage-07-capability-layer.d.ts +7 -4
- package/dist/boot/stage-07-capability-layer.js +2 -1
- package/dist/boot/stage-08-reapers.d.ts +7 -4
- package/dist/boot/stage-08-reapers.js +4 -2
- package/dist/boot/stage-09-leader.d.ts +11 -5
- package/dist/boot/stage-09-leader.js +12 -3
- package/dist/boot/stage-10-http-server.d.ts +11 -5
- package/dist/boot/stage-10-http-server.js +3 -6
- package/dist/boot/web-admin.js +3 -1
- package/dist/boot/workflow-orchestration.d.ts +7 -2
- package/dist/boot/workflow-orchestration.js +24 -7
- package/dist/bounded-rotation.d.ts +29 -0
- package/dist/bounded-rotation.js +24 -0
- package/dist/capability-facts.d.ts +22 -13
- package/dist/capability-facts.js +28 -18
- package/dist/center-credential.d.ts +25 -6
- package/dist/center-credential.js +25 -5
- package/dist/config-catalog.d.ts +26 -7
- package/dist/config-catalog.js +14 -11
- package/dist/config-invariants.d.ts +2 -1
- package/dist/config-invariants.js +4 -4
- package/dist/config-types.d.ts +10 -4
- package/dist/config.d.ts +51 -2
- package/dist/config.js +35 -24
- package/dist/deployment-shape.d.ts +9 -1
- package/dist/deployment-shape.js +2 -1
- package/dist/device-protocol.d.ts +5 -4
- package/dist/device-protocol.js +1 -1
- package/dist/device-ws-hub.js +3 -2
- package/dist/device-ws-protocol.d.ts +63 -10
- package/dist/device-ws-protocol.js +56 -25
- package/dist/engine-identity.d.ts +19 -7
- package/dist/engine-identity.js +10 -2
- package/dist/entry-mode-clamp-notice.d.ts +2 -1
- package/dist/execution-env-refusal.d.ts +23 -0
- package/dist/execution-env-refusal.js +5 -0
- package/dist/execution-lane-caps.d.ts +3 -1
- package/dist/field-conflict.d.ts +1 -1
- package/dist/file-history-capture.d.ts +11 -4
- package/dist/file-history-capture.js +9 -6
- package/dist/file-history-disclosure.d.ts +7 -5
- package/dist/file-history-disclosure.js +7 -5
- package/dist/fleet/drain-entry.d.ts +4 -0
- package/dist/hooks/hook-runner.js +2 -2
- package/dist/host-lsp-manager.d.ts +2 -2
- package/dist/http/admission.js +17 -2
- package/dist/http/approval-sweeps.js +5 -5
- package/dist/http/checkpoint-ctx.d.ts +2 -0
- package/dist/http/checkpoint-ctx.js +1 -0
- package/dist/http/dispatch.d.ts +2 -1
- package/dist/http/dispatch.js +34 -27
- package/dist/http/durable-run-leg.js +16 -16
- package/dist/http/health-self-report.d.ts +9 -1
- package/dist/http/health-self-report.js +2 -0
- package/dist/http/owner-access.d.ts +31 -11
- package/dist/http/owner-access.js +37 -6
- package/dist/http/resume-ctx-read.js +25 -3
- package/dist/http/resume-legs.d.ts +2 -1
- package/dist/http/resume-legs.js +259 -79
- package/dist/http/route-ctx.d.ts +18 -8
- package/dist/http/route-table.d.ts +1 -1
- package/dist/http/routes/admin-memory-optout.d.ts +1 -1
- package/dist/http/routes/agents-roster.js +2 -3
- package/dist/http/routes/approvals-assistant.js +4 -3
- package/dist/http/routes/background.d.ts +3 -3
- package/dist/http/routes/capabilities.js +8 -5
- package/dist/http/routes/fleet.js +10 -8
- package/dist/http/routes/projects.d.ts +3 -2
- package/dist/http/routes/projects.js +4 -5
- package/dist/http/routes/runs.js +102 -36
- package/dist/http/routes/session-sync.d.ts +4 -3
- package/dist/http/routes/session-sync.js +172 -77
- package/dist/http/routes/sessions-list.js +13 -7
- package/dist/http/routes/sessions.js +10 -6
- package/dist/http/routes/tasks.js +30 -16
- package/dist/http/routes/trace-usage.js +2 -2
- package/dist/http/server.d.ts +21 -27
- package/dist/http/server.js +2 -2
- package/dist/http/submit-ctx.js +5 -4
- package/dist/http/wire-types.d.ts +14 -4
- package/dist/identity-source.d.ts +20 -3
- package/dist/identity-source.js +14 -0
- package/dist/index.d.ts +4 -0
- package/dist/lane-home-probe.d.ts +3 -7
- package/dist/lane-home-probe.js +0 -1
- package/dist/leader/leader.d.ts +2 -1
- package/dist/leg-facts.d.ts +13 -5
- package/dist/leg-facts.js +2 -1
- package/dist/memory-scope.d.ts +5 -4
- package/dist/memory-scope.js +4 -4
- package/dist/memory-sync-client.d.ts +30 -2
- package/dist/memory-sync-client.js +16 -9
- package/dist/observability/err-text.d.ts +7 -0
- package/dist/observability/err-text.js +5 -0
- package/dist/observability/fail-open.d.ts +7 -3
- package/dist/observability/fail-open.js +7 -3
- package/dist/observability/metrics.js +1 -0
- package/dist/orchestration/workflow-notify-journal.d.ts +18 -1
- package/dist/orchestration/workflow-notify-journal.js +12 -1
- package/dist/orchestration/workflow-park-decision.d.ts +70 -18
- package/dist/orchestration/workflow-park-decision.js +49 -10
- package/dist/orchestration/workflow-park-holder.d.ts +65 -0
- package/dist/orchestration/workflow-park-holder.js +98 -0
- package/dist/orchestration/workflow-record-fence.d.ts +36 -0
- package/dist/orchestration/workflow-record-fence.js +42 -0
- package/dist/owner-faces.d.ts +1 -1
- package/dist/parked-decide.d.ts +104 -53
- package/dist/parked-decide.js +153 -117
- package/dist/peer-directory.d.ts +2 -2
- package/dist/peer-inbound-face.d.ts +2 -6
- package/dist/peer-inbound-face.js +0 -3
- package/dist/permission-mode-admission.d.ts +41 -5
- package/dist/permission-mode-admission.js +29 -3
- package/dist/plugins/adoption-log-sql.d.ts +3 -1
- package/dist/plugins/adoption-log-sql.js +7 -1
- package/dist/plugins/approval-ask-store-file.d.ts +10 -2
- package/dist/plugins/approval-ask-store-file.js +8 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +6 -1
- package/dist/plugins/approval-ask-store-memory.js +28 -9
- package/dist/plugins/approval-ask-store-sql.d.ts +43 -2
- package/dist/plugins/approval-ask-store-sql.js +34 -5
- package/dist/plugins/approval-exemption-store.js +3 -0
- package/dist/plugins/approval-nonce-store.js +2 -0
- package/dist/plugins/breaker-state-sql.js +2 -0
- package/dist/plugins/caching-session-store.d.ts +9 -15
- package/dist/plugins/caching-session-store.js +6 -0
- package/dist/plugins/device-store-sql.js +6 -0
- package/dist/plugins/error-origin.d.ts +18 -0
- package/dist/plugins/error-origin.js +10 -0
- package/dist/plugins/execution-placement-sql.js +6 -6
- package/dist/plugins/image-bake-store-sql.js +6 -0
- package/dist/plugins/image-index-sql.js +4 -0
- package/dist/plugins/landed-attendants.d.ts +212 -0
- package/dist/plugins/landed-attendants.js +161 -0
- package/dist/plugins/leader-run-store-sql.js +4 -0
- package/dist/plugins/local-session-live-reference.d.ts +40 -0
- package/dist/plugins/local-session-live-reference.js +39 -0
- package/dist/plugins/local-session-store.d.ts +71 -33
- package/dist/plugins/local-session-store.js +129 -27
- package/dist/plugins/memory-engine-pg.js +4 -0
- package/dist/plugins/memory-engine-sql-apply.js +5 -2
- package/dist/plugins/memory-engine-tidb.js +4 -0
- package/dist/plugins/memory-optout-grant-store-sql.js +4 -0
- package/dist/plugins/memory-sync-store-pg.js +5 -0
- package/dist/plugins/memory-sync-store-tidb.js +5 -0
- package/dist/plugins/one-time-migrations.d.ts +57 -63
- package/dist/plugins/one-time-migrations.js +162 -90
- package/dist/plugins/org-delivery-quota-store.js +4 -1
- package/dist/plugins/outcome-ledger-sql.js +2 -0
- package/dist/plugins/permission-rule-store-sql.js +11 -4
- package/dist/plugins/pg-cost-quota.js +4 -0
- package/dist/plugins/pg-pool.js +24 -1
- package/dist/plugins/pg-rate-limiter.js +2 -0
- package/dist/plugins/posix-shell-fs.d.ts +6 -1
- package/dist/plugins/posix-shell-fs.js +4 -1
- package/dist/plugins/remote-env-adb.d.ts +19 -15
- package/dist/plugins/remote-env-adb.js +41 -15
- package/dist/plugins/remote-env-connect-seat.d.ts +105 -0
- package/dist/plugins/remote-env-connect-seat.js +72 -0
- package/dist/plugins/remote-env-device.d.ts +22 -5
- package/dist/plugins/remote-env-device.js +106 -8
- package/dist/plugins/remote-env-e2b.d.ts +15 -6
- package/dist/plugins/remote-env-e2b.js +42 -32
- package/dist/plugins/remote-env-file-error.js +6 -2
- package/dist/plugins/remote-env-host.d.ts +17 -0
- package/dist/plugins/remote-env-host.js +30 -38
- package/dist/plugins/remote-env-k8s.d.ts +41 -39
- package/dist/plugins/remote-env-k8s.js +53 -30
- package/dist/plugins/remote-env-local-docker.d.ts +13 -8
- package/dist/plugins/remote-env-local-docker.js +34 -41
- package/dist/plugins/remote-env-ssh.d.ts +18 -12
- package/dist/plugins/remote-env-ssh.js +60 -59
- package/dist/plugins/remote-shell.d.ts +98 -1
- package/dist/plugins/remote-shell.js +218 -0
- package/dist/plugins/resume-anchor-store-sql.d.ts +11 -2
- package/dist/plugins/resume-anchor-store-sql.js +12 -5
- package/dist/plugins/retention-lane-store-sql.js +4 -0
- package/dist/plugins/retention-sql.d.ts +20 -2
- package/dist/plugins/retention-sql.js +11 -0
- package/dist/plugins/run-store-sql.d.ts +21 -2
- package/dist/plugins/run-store-sql.js +31 -7
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +1 -1
- package/dist/plugins/scenario-prefix-switch-m42.js +2 -2
- package/dist/plugins/schema-consistency.d.ts +4 -2
- package/dist/plugins/schema-consistency.js +19 -2
- package/dist/plugins/send-file-ledger.js +3 -0
- package/dist/plugins/serving-requirement.d.ts +26 -7
- package/dist/plugins/serving-requirement.js +11 -4
- package/dist/plugins/session-birth.d.ts +6 -2
- package/dist/plugins/session-capture-record-store-sql.js +2 -0
- package/dist/plugins/session-ext-table.d.ts +14 -1
- package/dist/plugins/session-ext-table.js +5 -1
- package/dist/plugins/session-row-sql.d.ts +49 -2
- package/dist/plugins/session-row-sql.js +56 -13
- package/dist/plugins/session-store-sql.d.ts +34 -18
- package/dist/plugins/session-store-sql.js +98 -17
- package/dist/plugins/shared-memory-store-sql.d.ts +1 -0
- package/dist/plugins/shared-memory-store-sql.js +6 -2
- package/dist/plugins/sql-driver.d.ts +2 -1
- package/dist/plugins/sql-driver.js +18 -3
- package/dist/plugins/sql-errors.d.ts +11 -6
- package/dist/plugins/sql-errors.js +5 -6
- package/dist/plugins/stop-then-start-sentence.d.ts +10 -4
- package/dist/plugins/stop-then-start-sentence.js +14 -10
- package/dist/plugins/stop-then-start.d.ts +109 -0
- package/dist/plugins/stop-then-start.js +104 -0
- package/dist/plugins/store-backend.d.ts +40 -13
- package/dist/plugins/store-backend.js +169 -27
- package/dist/plugins/store-boundary.d.ts +57 -0
- package/dist/plugins/store-boundary.js +139 -0
- package/dist/plugins/store-contracts.d.ts +17 -0
- package/dist/plugins/store-fault-sentence-m53.d.ts +7 -0
- package/dist/plugins/store-fault-sentence-m53.js +25 -0
- package/dist/plugins/store-fault.d.ts +26 -7
- package/dist/plugins/store-fault.js +18 -2
- package/dist/plugins/task-attachment-store.js +9 -0
- package/dist/plugins/task-list-store-sql.d.ts +2 -2
- package/dist/plugins/task-list-store-sql.js +10 -8
- package/dist/plugins/tidb-cost-quota.js +4 -0
- package/dist/plugins/tidb-pool.js +2 -1
- package/dist/plugins/tidb-rate-limiter.js +4 -0
- package/dist/plugins/user-input-ledger-sql.js +4 -0
- package/dist/plugins/workflow-run-store-sql.d.ts +28 -10
- package/dist/plugins/workflow-run-store-sql.js +64 -4
- package/dist/plugins/workspace-fill.d.ts +4 -7
- package/dist/plugins/workspace-fill.js +2 -1
- package/dist/plugins/write-behind-counter.js +5 -0
- package/dist/project-context.d.ts +0 -2
- package/dist/project-context.js +4 -8
- package/dist/project-registry.d.ts +46 -0
- package/dist/project-registry.js +44 -0
- package/dist/request-key-closure.js +1 -1
- package/dist/request-value-closure.d.ts +4 -0
- package/dist/request-value-closure.js +10 -0
- package/dist/run-acceptance.d.ts +3 -2
- package/dist/run-acceptance.js +4 -6
- package/dist/run-local.js +1 -0
- package/dist/runs.d.ts +37 -8
- package/dist/runs.js +53 -12
- package/dist/runtime-governance.d.ts +5 -4
- package/dist/security.d.ts +30 -32
- package/dist/security.js +41 -7
- package/dist/server-secret-env.d.ts +12 -10
- package/dist/server-secret-env.js +24 -15
- package/dist/session-bindings.d.ts +82 -0
- package/dist/session-bindings.js +18 -0
- package/dist/session-children-retire.d.ts +2 -2
- package/dist/session-children-retire.js +2 -6
- package/dist/session-deletion.d.ts +16 -1
- package/dist/session-error-wire.d.ts +3 -3
- package/dist/session-error-wire.js +3 -3
- package/dist/session-incarnation.d.ts +10 -0
- package/dist/session-incarnation.js +10 -1
- package/dist/session-kind.d.ts +57 -0
- package/dist/session-kind.js +22 -0
- package/dist/session-row.d.ts +21 -1
- package/dist/session-row.js +7 -1
- package/dist/session-sync-kernel.d.ts +24 -14
- package/dist/session-sync-kernel.js +3 -6
- package/dist/session-sync.d.ts +4 -98
- package/dist/session-sync.js +1 -71
- package/dist/session-titler.d.ts +10 -3
- package/dist/session-titler.js +19 -6
- package/dist/ssh-host-key.d.ts +5 -0
- package/dist/ssh-host-key.js +3 -0
- package/dist/stores-sql/file-history-store-sql.d.ts +52 -2
- package/dist/stores-sql/file-history-store-sql.js +108 -70
- package/dist/stores-sql/pg-session-storage.d.ts +34 -7
- package/dist/stores-sql/pg-session-storage.js +37 -13
- package/dist/stores-sql/retention-store-sql.d.ts +1 -9
- package/dist/stores-sql/retention-store-sql.js +2 -10
- package/dist/stores-sql/session-policy-store-sql.d.ts +30 -7
- package/dist/stores-sql/session-policy-store-sql.js +61 -44
- package/dist/stores-sql/session-write-hooks.d.ts +11 -0
- package/dist/stores-sql/tidb-session-store.d.ts +58 -7
- package/dist/stores-sql/tidb-session-store.js +37 -13
- package/dist/submission-exit.d.ts +3 -2
- package/dist/submission-exit.js +9 -1
- package/dist/task-cwd.d.ts +2 -2
- package/dist/task-settings.d.ts +6 -5
- package/dist/terminal.d.ts +33 -2
- package/dist/terminal.js +139 -9
- package/dist/tool-approval.d.ts +140 -6
- package/dist/tool-approval.js +165 -72
- package/dist/trace/self-minted-wire.d.ts +290 -27
- package/dist/trace/self-minted-wire.js +101 -13
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +78 -27
- package/package.json +2 -2
- package/wire-changes/server@7.151.0.json +762 -0
- package/dist/http/session-inherit-env.d.ts +0 -36
- package/dist/http/session-inherit-env.js +0 -6
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
import type { FlatServiceDeps } from "./http/server.js";
|
|
22
22
|
import type { ServiceConfig } from "./config.js";
|
|
23
23
|
import type { OwnerAwareSessionStore } from "./security.js";
|
|
24
|
-
import type { ServiceBlobExchange, ServiceFileHistoryStore } from "./plugins/store-backend.js";
|
|
24
|
+
import type { ServiceBlobExchange, ServiceFileHistoryStore, StoreBackend } from "./plugins/store-backend.js";
|
|
25
25
|
import { resolveStreamApprovalGate, type ApprovalFrameFamily } from "./tool-approval.js";
|
|
26
26
|
import { type WorkspaceSyncCapability } from "./workspace-space.js";
|
|
27
27
|
import type { WorkspaceCacheCapability } from "./workspace-cache.js";
|
|
@@ -42,7 +42,7 @@ export declare const CAPABILITY_FACT_WHY: {
|
|
|
42
42
|
readonly session_fork_face_absent: "the session store has no fork face";
|
|
43
43
|
readonly session_row_faces_absent: "the session store has no session-row faces (headOf / sessionSummaryOf / writeSessionRowCells)";
|
|
44
44
|
readonly session_purge_absent: "no session purge coordinator is wired";
|
|
45
|
-
readonly
|
|
45
|
+
readonly session_kind_faces_absent: "the session store cannot record a session kind (it needs the birth receipt face that takes a kind, sessionKindOf, listSessions and listIdleOfKind) or no session purge coordinator is wired to age such sessions out";
|
|
46
46
|
readonly store_backend_absent: "no store backend is wired (DB_BACKEND=memory, multi-tenant bare boot, or half-configured SQL)";
|
|
47
47
|
readonly file_history_store_absent: "no file-history store is wired";
|
|
48
48
|
readonly resume_anchor_store_absent: "no rewind anchor map is wired (the handle → session-entry map a rewind target is read through, with the run store an unknown handle is checked against — both come from the store backend)";
|
|
@@ -187,6 +187,12 @@ type SessionLister = NonNullable<OwnerAwareSessionStore["listSessions"]>;
|
|
|
187
187
|
export declare function sessionList(d: Pick<Deps, "sessionStorage">): Fact<"session_lister_absent", {
|
|
188
188
|
lister: SessionLister;
|
|
189
189
|
}>;
|
|
190
|
+
/**
|
|
191
|
+
* 会话种类在场(律 `session-kind.ts`):会话店交「带种类的出生回执」(`registerWithReceipt` 的第三参;授权口登记新行的那一笔)∧ 按 id 的种类读 `sessionKindOf`(既有会话上的比对)
|
|
192
|
+
* ∧ 列表面 `listSessions`(视图谓词在店里)∧ 老化候选面 `listIdleOfKind` ∧ 删除协调器(老化删走它)。读者三只、同读这一只:能力位 `capabilities.sessionKinds`、
|
|
193
|
+
* 受理门的 `request.precondition_unmet`、授权口的种类判。三只持久店恒在;内存店不在。
|
|
194
|
+
*/
|
|
195
|
+
export declare function sessionKinds(d: Pick<Deps, "sessionStorage" | "purgeSession">): Fact<"session_kind_faces_absent">;
|
|
190
196
|
export declare function sessionFork<D extends SessionDeps>(d: D): Fact<"session_fork_face_absent" | "session_head_face_absent", {
|
|
191
197
|
sessionStorage: SessionWith<D, "headOf" | "fork">;
|
|
192
198
|
}>;
|
|
@@ -204,40 +210,42 @@ export declare function sessionDelete<D extends Pick<Deps, "purgeSession" | "ses
|
|
|
204
210
|
purge: Store<"purgeSession">;
|
|
205
211
|
sessionStorage: HeadReadingSessionStore<D>;
|
|
206
212
|
}>;
|
|
207
|
-
|
|
208
|
-
|
|
213
|
+
/** 会话规则面(`GET` / `PUT /v1/sessions/:id/policy`):后端 ∧ 会话头读。见证交后端:`GET` 读 `backend.sessionPolicy()`(恒同一只 —— 引擎的规则席读同一只),
|
|
214
|
+
* `PUT` 写经同一只后端的落定席位 `landedAttendants()`(段首锁会话根行判门读的那一位住客,门后会话被删 / 同 id 重建 ⇒ 零写)写进的就是那一只。读与写同出一只后端,没有第二个店源。 */
|
|
215
|
+
export declare function sessionPolicy<D extends Pick<Deps, "sessionStorage" | "backend">>(d: D): Fact<"session_head_face_absent" | "store_backend_absent", {
|
|
209
216
|
sessionStorage: HeadReadingSessionStore<D>;
|
|
217
|
+
backend: StoreBackend;
|
|
210
218
|
}>;
|
|
211
219
|
type SyncSessionStore<D extends SessionDeps> = SessionWith<D, "exportEntries" | "exportEntriesStream" | "beginImportStaging" | "headOf" | "sessionSummaryOf" | "writeSessionRowCells">;
|
|
212
|
-
type SessionSyncWhy = "store_backend_absent" | "
|
|
213
|
-
/** 会话对等同步的**对话半族**(manifest / entries / plan / import 两相):后端
|
|
220
|
+
type SessionSyncWhy = "store_backend_absent" | "session_export_absent" | "session_import_staging_absent" | "session_row_faces_absent" | "policy_purge_absent";
|
|
221
|
+
/** 会话对等同步的**对话半族**(manifest / entries / plan / import 两相):后端(文件历史店 / 规则店 / 锚店都是它恒交的那一只,落定席位写的同一只)∧ 导出两面 ∧ staged 导入面 ∧
|
|
214
222
|
* 会话行三口(门读头 `headOf` —— 属主 + 化身一次读,属主判门、化身给 identical 短路腿;manifest 带 `title` / `pinned`;导入经行格写原语以 `replay` 写者
|
|
215
223
|
* 按导入落定的那一位住客重放它们)∧ policy 店能清(overwrite-dst 的 commit 要擦目的端旧 policy 行)。
|
|
216
224
|
* 文件历史的 blob 搬运是另一只事实。 */
|
|
217
|
-
export declare function sessionSync<D extends Pick<Deps, "backend" | "sessionStorage"
|
|
225
|
+
export declare function sessionSync<D extends Pick<Deps, "backend" | "sessionStorage">>(d: D): Fact<SessionSyncWhy, {
|
|
218
226
|
backend: Held<D, "backend">;
|
|
219
227
|
sessionStorage: SyncSessionStore<D>;
|
|
220
228
|
historyStore: ServiceFileHistoryStore;
|
|
221
229
|
}>;
|
|
222
230
|
/** 会话同步的**文件历史半族**:对话半族 ∧ 文件历史店带 blob 交换组(只有 SQL 两只店有)。「店能不能交换 blob」只在 `blobExchangeOf` 判一次(core 判官),
|
|
223
231
|
* blob 取值口 `blobGetterOf` 读的是同一只 —— 本事实为真 ⟺ 取值口通到 `blobExchange.get`;判过的组随事实交出,路由的 GET / PUT / 在场预检只读它。 */
|
|
224
|
-
export declare function sessionSyncFileHistory(d: Pick<Deps, "backend" | "sessionStorage"
|
|
232
|
+
export declare function sessionSyncFileHistory(d: Pick<Deps, "backend" | "sessionStorage">): Fact<SessionSyncWhy | "blob_exchange_absent", {
|
|
225
233
|
historyStore: ServiceFileHistoryStore;
|
|
226
234
|
blobExchange: ServiceBlobExchange;
|
|
227
235
|
}>;
|
|
228
236
|
type RewindFilesWhy = "file_history_store_absent" | "session_head_face_absent" | "resume_anchor_store_absent" | "execution_lane_handless" | "workspace_rebuilt_per_task" | "session_store_shared";
|
|
229
237
|
/**
|
|
230
238
|
* run 外的「只恢复代码」口(`POST /v1/sessions/:id/rewind-files`,[ref])这台部署**解不解得出** —— 能力位 `sessionRewindFiles` 与该口的 501 读这一只。
|
|
231
|
-
* 四格缺一不可,每格都是那一口真要用的设施:文件历史店(引擎 `Runner.rewindFiles`
|
|
232
|
-
*
|
|
233
|
-
* `history-anchor.ts
|
|
239
|
+
* 四格缺一不可,每格都是那一口真要用的设施:文件历史店(后端恒交的那一只 —— 引擎 `Runner.rewindFiles` 读的同一只;没有后端 ⇒ 没有它;旋钮 `FILE_HISTORY_CAPTURE` 只关捕获、
|
|
240
|
+
* 不摘店,所以与它无关 —— 已存边界照常可回退)∧ 会话头读(属主门 + 坏档判据)∧ 锚店与 run 店(`to` 手柄经锚店翻成 entry id,未知手柄的 404 成因半句读 run 店,
|
|
241
|
+
* `history-anchor.ts`;锚店是后端恒交的那一只,run 店同出存储后端,所以是同一格)∧ 执行车道有手
|
|
234
242
|
* (无手车道上引擎恒拒 `rewind.files_env_unsupported`:没有工作区可回退 —— 位说有而口恒拒不许发生)∧ 即时回退的工作区活过一次执行(部署形表行 `rewindableWorkspace`;
|
|
235
243
|
* 否则恢复的结果到不了下一次执行)∧ 会话店由本进程独占(local 后端:数据根被一个活进程锁住 ⇒ 引擎的进程内会话锁就是全局互斥;
|
|
236
244
|
* SQL 后端被多副本共用,而 run 外回退还没有一只跨副本的持久认领 —— 「先查认领再交引擎」只是检查不是互斥,所以在共享店上位为假、口 501,不留「检查即放行」)。
|
|
237
245
|
* 动词本身是引擎 `Runner` 的必有成员(型上必在),不是一格。
|
|
238
246
|
* 见证 = 判过在场的设施(历史店 · 手柄翻译的两只读店 · 会话店);路由在拒臂之后只读见证。
|
|
239
247
|
*/
|
|
240
|
-
export declare function sessionRewindFiles<D extends Pick<Deps, "
|
|
248
|
+
export declare function sessionRewindFiles<D extends Pick<Deps, "runStore" | "sessionStorage" | "config" | "backend">>(d: D): Fact<RewindFilesWhy, {
|
|
241
249
|
historyStore: ServiceFileHistoryStore;
|
|
242
250
|
anchors: HistoryAnchorReaders & {
|
|
243
251
|
readonly runs: Held<D, "runStore">;
|
|
@@ -250,7 +258,7 @@ export declare function sessionRewindFiles<D extends Pick<Deps, "fileHistoryStor
|
|
|
250
258
|
* `previewFileDelta` 不在 core 包根导出面上,本仓不另写一份 —— 等 core 导出它,SQL 店补这一座、本位随之转真,路由零改)。本位为假**不是**口不收 `dryRun`:口照收,答 `preview: null`
|
|
251
259
|
* (「这台给不出统计」≠「什么都不会变」);所以本事实没有 501 拒点,只有能力位读它。
|
|
252
260
|
*/
|
|
253
|
-
export declare function sessionRewindFilesPreview(d: Pick<Deps, "
|
|
261
|
+
export declare function sessionRewindFilesPreview(d: Pick<Deps, "runStore" | "sessionStorage" | "config" | "backend">): Fact<RewindFilesWhy | "file_history_preview_absent">;
|
|
254
262
|
/** 持久审批底座(checkpoint 店)在场 —— `/v1/approvals/*` 与 `/v1/assistant/*` 整条车道、会话 wake 都站在它上面。 */
|
|
255
263
|
export declare function checkpointPark(d: Pick<Deps, "checkpointStore">): Fact<"checkpoint_store_absent", {
|
|
256
264
|
checkpointStore: Store<"checkpointStore">;
|
|
@@ -271,6 +279,7 @@ type ActiveStreamApproval = Extract<ReturnType<typeof resolveStreamApprovalGate>
|
|
|
271
279
|
/** 流内审批协议在场 —— 判据的属主仍是 `resolveStreamApprovalGate`(三条执行腿的装配也读它);本事实把它的拒因译进 why 闭集。 */
|
|
272
280
|
export declare function streamApproval(d: Pick<Deps, "toolApproval" | "config" | "backend" | "checkpointStore">): Fact<StreamApprovalWhy, {
|
|
273
281
|
askStore: ActiveStreamApproval["askStore"];
|
|
282
|
+
coordinator: Store<"toolApproval">;
|
|
274
283
|
}>;
|
|
275
284
|
/**
|
|
276
285
|
* 读根授权(「Yes, and add directory」)这台部署**受理不受理** —— `GET /v1/capabilities` 的 `approvalReadRootGrant` 位,与
|
package/dist/capability-facts.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { assembleFileHistory } from "./file-history-capture.js";
|
|
1
2
|
import { buildOperatorRosterWayOut, operatorRosterPresent } from "./http/principal-gate.js";
|
|
2
3
|
import { mcpInjectionHonored } from "./task-mcp.js";
|
|
3
4
|
import { DEPLOYMENT_SHAPE_PREDICATES } from "./deployment-shape.js";
|
|
@@ -5,8 +6,11 @@ import { presentedApprovalFrameFamily, resolveStreamApprovalGate } from "./tool-
|
|
|
5
6
|
import { selfOrchestrationDenial } from "./task-workflow.js";
|
|
6
7
|
import { centerEntitlementSourceWired } from "./runtime-caps-resolver.js";
|
|
7
8
|
import { WEB_ADMIN_ENV } from "@sema-agent/settings-schema";
|
|
8
|
-
import { blobExchangeOf
|
|
9
|
+
import { blobExchangeOf } from "./session-sync.js";
|
|
10
|
+
import { overwriteWipeIncapable } from "./plugins/landed-attendants.js";
|
|
9
11
|
import { WORKSPACE_PERSIST_DEFAULT, WORKSPACE_SNAPSHOT_KEEP_DEFAULT, workspaceSnapshotTimeoutOf } from "./workspace-space.js";
|
|
12
|
+
import { sessionKindFaceOf } from "./session-kind.js";
|
|
13
|
+
import { birthFaceOf } from "./plugins/session-birth.js";
|
|
10
14
|
import { headReadPresent } from "./session-incarnation.js";
|
|
11
15
|
import { laneWiresExecutionEnv } from "./execution-lane-caps.js";
|
|
12
16
|
export const CAPABILITY_FACT_WHY = {
|
|
@@ -23,7 +27,7 @@ export const CAPABILITY_FACT_WHY = {
|
|
|
23
27
|
session_fork_face_absent: "the session store has no fork face",
|
|
24
28
|
session_row_faces_absent: "the session store has no session-row faces (headOf / sessionSummaryOf / writeSessionRowCells)",
|
|
25
29
|
session_purge_absent: "no session purge coordinator is wired",
|
|
26
|
-
|
|
30
|
+
session_kind_faces_absent: "the session store cannot record a session kind (it needs the birth receipt face that takes a kind, sessionKindOf, listSessions and listIdleOfKind) or no session purge coordinator is wired to age such sessions out",
|
|
27
31
|
store_backend_absent: "no store backend is wired (DB_BACKEND=memory, multi-tenant bare boot, or half-configured SQL)",
|
|
28
32
|
file_history_store_absent: "no file-history store is wired",
|
|
29
33
|
resume_anchor_store_absent: "no rewind anchor map is wired (the handle → session-entry map a rewind target is read through, with the run store an unknown handle is checked against — both come from the store backend)",
|
|
@@ -156,6 +160,12 @@ export function sessionList(d) {
|
|
|
156
160
|
const lister = d.sessionStorage?.listSessions?.bind(d.sessionStorage);
|
|
157
161
|
return lister !== undefined ? yes({ lister }) : no("session_lister_absent");
|
|
158
162
|
}
|
|
163
|
+
export function sessionKinds(d) {
|
|
164
|
+
const s = d.sessionStorage;
|
|
165
|
+
return birthFaceOf(s) !== undefined && sessionKindFaceOf(s) !== undefined && typeof s?.listSessions === "function" && typeof s.listIdleOfKind === "function" && d.purgeSession !== undefined
|
|
166
|
+
? YES
|
|
167
|
+
: no("session_kind_faces_absent");
|
|
168
|
+
}
|
|
159
169
|
export function sessionFork(d) {
|
|
160
170
|
const s = d.sessionStorage;
|
|
161
171
|
if (s?.fork === undefined)
|
|
@@ -180,21 +190,18 @@ export function sessionDelete(d) {
|
|
|
180
190
|
return yes({ purge, sessionStorage: owned.sessionStorage });
|
|
181
191
|
}
|
|
182
192
|
export function sessionPolicy(d) {
|
|
183
|
-
const
|
|
184
|
-
if (
|
|
185
|
-
return no("
|
|
193
|
+
const backend = d.backend;
|
|
194
|
+
if (backend === undefined)
|
|
195
|
+
return no("store_backend_absent");
|
|
186
196
|
const owned = sessionOwnership(d);
|
|
187
197
|
if (!owned.available)
|
|
188
198
|
return owned;
|
|
189
|
-
return yes({
|
|
199
|
+
return yes({ sessionStorage: owned.sessionStorage, backend });
|
|
190
200
|
}
|
|
191
201
|
export function sessionSync(d) {
|
|
192
|
-
const { fileHistoryStore: historyStore, sessionPolicyStore } = d;
|
|
193
202
|
const backend = d.backend;
|
|
194
203
|
if (backend === undefined)
|
|
195
204
|
return no("store_backend_absent");
|
|
196
|
-
if (historyStore === undefined)
|
|
197
|
-
return no("file_history_store_absent");
|
|
198
205
|
const s = d.sessionStorage;
|
|
199
206
|
if (s?.exportEntries === undefined || s.exportEntriesStream === undefined)
|
|
200
207
|
return no("session_export_absent");
|
|
@@ -202,9 +209,9 @@ export function sessionSync(d) {
|
|
|
202
209
|
return no("session_import_staging_absent");
|
|
203
210
|
if (!headReadPresent(s) || s.sessionSummaryOf === undefined || s.writeSessionRowCells === undefined)
|
|
204
211
|
return no("session_row_faces_absent");
|
|
205
|
-
if (overwriteWipeIncapable(
|
|
212
|
+
if (overwriteWipeIncapable(backend.sessionPolicy()))
|
|
206
213
|
return no("policy_purge_absent");
|
|
207
|
-
return yes({ backend, sessionStorage: s, historyStore });
|
|
214
|
+
return yes({ backend, sessionStorage: s, historyStore: assembleFileHistory(backend).store });
|
|
208
215
|
}
|
|
209
216
|
export function sessionSyncFileHistory(d) {
|
|
210
217
|
const sync = sessionSync(d);
|
|
@@ -214,22 +221,22 @@ export function sessionSyncFileHistory(d) {
|
|
|
214
221
|
return blobExchange !== undefined ? yes({ historyStore: sync.historyStore, blobExchange }) : no("blob_exchange_absent");
|
|
215
222
|
}
|
|
216
223
|
export function sessionRewindFiles(d) {
|
|
217
|
-
const {
|
|
218
|
-
if (
|
|
224
|
+
const { config, backend } = d;
|
|
225
|
+
if (backend === undefined)
|
|
219
226
|
return no("file_history_store_absent");
|
|
220
227
|
const owned = sessionOwnership(d);
|
|
221
228
|
if (!owned.available)
|
|
222
229
|
return owned;
|
|
223
230
|
const runs = durableRuns(d);
|
|
224
|
-
if (
|
|
231
|
+
if (!runs.available)
|
|
225
232
|
return no("resume_anchor_store_absent");
|
|
226
233
|
if (!laneWiresExecutionEnv(config.remoteExec.provider))
|
|
227
234
|
return no("execution_lane_handless");
|
|
228
235
|
if (!DEPLOYMENT_SHAPE_PREDICATES.rewindableWorkspace.holds(config))
|
|
229
236
|
return no("workspace_rebuilt_per_task");
|
|
230
|
-
if (backend
|
|
237
|
+
if (backend.kind !== "local")
|
|
231
238
|
return no("session_store_shared");
|
|
232
|
-
return yes({ historyStore, anchors: { anchors, runs: runs.runStore }, sessionStorage: owned.sessionStorage });
|
|
239
|
+
return yes({ historyStore: assembleFileHistory(backend).store, anchors: { anchors: backend.resumeAnchor(), runs: runs.runStore }, sessionStorage: owned.sessionStorage });
|
|
233
240
|
}
|
|
234
241
|
export function sessionRewindFilesPreview(d) {
|
|
235
242
|
const rewind = sessionRewindFiles(d);
|
|
@@ -250,14 +257,17 @@ export function toolApproval(d) {
|
|
|
250
257
|
return d.toolApproval !== undefined ? yes({ coordinator: d.toolApproval }) : no("tool_approval_disabled");
|
|
251
258
|
}
|
|
252
259
|
export function streamApproval(d) {
|
|
260
|
+
if (d.toolApproval === undefined)
|
|
261
|
+
return no("tool_approval_disabled");
|
|
262
|
+
const coordinator = d.toolApproval;
|
|
253
263
|
const gate = resolveStreamApprovalGate({
|
|
254
|
-
toolApprovalEnabled:
|
|
264
|
+
toolApprovalEnabled: true,
|
|
255
265
|
streamApprovalEnabled: d.config.streamApproval?.enabled === true,
|
|
256
266
|
backend: d.backend,
|
|
257
267
|
checkpointStore: d.checkpointStore,
|
|
258
268
|
});
|
|
259
269
|
if (gate.active)
|
|
260
|
-
return yes({ askStore: gate.askStore });
|
|
270
|
+
return yes({ askStore: gate.askStore, coordinator });
|
|
261
271
|
switch (gate.reason) {
|
|
262
272
|
case "no_tool_approval":
|
|
263
273
|
return no("tool_approval_disabled");
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { type WebAdminCredentialDeclaration } from "@sema-agent/settings-schema";
|
|
1
|
+
import { type WebAdminCredential, type WebAdminCredentialDeclaration } from "@sema-agent/settings-schema";
|
|
2
2
|
/** 凭证种类闭集。新增一个种类 = 本文件与 `web-admin-client/center-request.ts` 的穷举 switch 当场编译红。 */
|
|
3
3
|
export type CenterCredentialKind = "pull-token" | "user-jwt" | "user-session" | "none";
|
|
4
4
|
/** 一次取值失败的成因闭集(见模块头注「四个成因」;boot 判决 {@link judgeCenterCredentialAtBoot} 对它穷举)。 */
|
|
5
5
|
export type CenterCredentialFailure = "missing" | "malformed" | "multi_tenant_session" | "expired";
|
|
6
|
-
/** 声明形的**非秘密**投影(进日志 / 拒因 /
|
|
6
|
+
/** 声明形的**非秘密**投影(进日志 / 拒因 / 自报位):env 形不带值。唯一铸点 {@link credentialOriginOf}。 */
|
|
7
7
|
export type CenterCredentialOrigin = {
|
|
8
8
|
readonly from: "env";
|
|
9
9
|
} | {
|
|
@@ -12,6 +12,10 @@ export type CenterCredentialOrigin = {
|
|
|
12
12
|
} | {
|
|
13
13
|
readonly from: "absent";
|
|
14
14
|
};
|
|
15
|
+
/** 声明**在**的那两形(配置里 `webAdmin.assertionToken` 的型:没声明 ⇒ 那一格缺席,缺席只有一种读法)。 */
|
|
16
|
+
export type DeclaredCredentialOrigin = Exclude<CenterCredentialOrigin, {
|
|
17
|
+
readonly from: "absent";
|
|
18
|
+
}>;
|
|
15
19
|
/**
|
|
16
20
|
* 一次取值的结果。`ok:false` 只有文件形会出现(env / absent 形的取值恒成功)。
|
|
17
21
|
* `identity` 是「此刻的凭证是谁」—— 成功恒在;失败时只有 `expired` 知道(信封还读得出 `sub`,只是令牌不许再出站),
|
|
@@ -92,11 +96,26 @@ export type CenterCredentialSourceSpec = Exclude<WebAdminCredentialDeclaration,
|
|
|
92
96
|
readonly multiTenant: boolean;
|
|
93
97
|
};
|
|
94
98
|
/**
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
99
|
+
* 读一份 web-admin 凭证(`credential` ∈ 契约闭集 `WEB_ADMIN_CREDENTIALS`)的那一对声明键 —— 两份凭证的**唯一**读口。判定全交 settings-schema 的判官
|
|
100
|
+
* `judgeWebAdminCredentialDeclaration`([ref]:二选一规则的**唯一**实现;空串 = 未设、不 trim;两个都设 ⇒ throw,boot 拒启,拒句点名那一对键、不回显值;
|
|
101
|
+
* 判哪一份由调用方说,判官没有缺省)。本仓只多读方自己的那一步:文件路径按本进程 cwd 解析成绝对路径(之后 cwd 变了也读同一个文件 —— 纯契约不碰
|
|
102
|
+
* `node:path`,这一步归读方)。
|
|
103
|
+
*/
|
|
104
|
+
export declare function readWebAdminCredentialDeclaration(credential: WebAdminCredential, env?: Readonly<Record<string, string | undefined>>): WebAdminCredentialDeclaration;
|
|
105
|
+
/** 声明 → 非秘密投影的**唯一**铸点(env 形丢掉值)。凭证来源的 `origin` 与断言令牌的配置读数都经它。 */
|
|
106
|
+
export declare function credentialOriginOf(declared: Readonly<{
|
|
107
|
+
from: "env";
|
|
108
|
+
} | {
|
|
109
|
+
from: "file";
|
|
110
|
+
path: string;
|
|
111
|
+
} | {
|
|
112
|
+
from: "absent";
|
|
113
|
+
}>): CenterCredentialOrigin;
|
|
114
|
+
/**
|
|
115
|
+
* [ref] —— 起服日志 `center_assertion_token` 的字段(`build*`:纯数据;`boot/web-admin.ts` 接了中心时打一次,info 级)。声明在 ⇒ 来源形(文件形另带
|
|
116
|
+
* 绝对路径;值形不带值);没声明 ⇒ 只有 `declared:false`。`effect` 如实说这一份凭证此刻的用途:只被读出声明,没有任何请求出示它。
|
|
98
117
|
*/
|
|
99
|
-
export declare function
|
|
118
|
+
export declare function buildAssertionTokenBootFields(declared: DeclaredCredentialOrigin | undefined): Readonly<Record<string, string | boolean>>;
|
|
100
119
|
/**
|
|
101
120
|
* 凭证来源工厂(活对象:文件形每次取值读盘并记健康态)。`worker` = `SEMA_WEB_ADMIN_WORKER`(拉取令牌形的身份)。
|
|
102
121
|
* `readFile` / `now` 只为测试注入。
|
|
@@ -12,10 +12,30 @@ export class CenterCredentialUnavailableError extends Error {
|
|
|
12
12
|
this.name = "CenterCredentialUnavailableError";
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
-
export function
|
|
16
|
-
const declared = judgeWebAdminCredentialDeclaration(env,
|
|
15
|
+
export function readWebAdminCredentialDeclaration(credential, env = process.env) {
|
|
16
|
+
const declared = judgeWebAdminCredentialDeclaration(env, credential);
|
|
17
17
|
return declared.from === "file" ? { from: "file", path: resolvePath(declared.path) } : declared;
|
|
18
18
|
}
|
|
19
|
+
export function credentialOriginOf(declared) {
|
|
20
|
+
switch (declared.from) {
|
|
21
|
+
case "env":
|
|
22
|
+
return { from: "env" };
|
|
23
|
+
case "file":
|
|
24
|
+
return { from: "file", path: declared.path };
|
|
25
|
+
case "absent":
|
|
26
|
+
return { from: "absent" };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export function buildAssertionTokenBootFields(declared) {
|
|
30
|
+
if (declared === undefined)
|
|
31
|
+
return { declared: false };
|
|
32
|
+
return {
|
|
33
|
+
declared: true,
|
|
34
|
+
from: declared.from,
|
|
35
|
+
...(declared.from === "file" ? { path: declared.path } : {}),
|
|
36
|
+
effect: "the declaration is read and reported only (GET /health center.assertionToken); no request from this engine presents the assertion token to the center",
|
|
37
|
+
};
|
|
38
|
+
}
|
|
19
39
|
const digest16 = (s) => createHash("sha256").update(s, "utf8").digest("hex").slice(0, 16);
|
|
20
40
|
function jwtSubject(bearer) {
|
|
21
41
|
let parsed;
|
|
@@ -90,10 +110,10 @@ export function createCenterCredentialSource(spec, worker, deps = {}) {
|
|
|
90
110
|
};
|
|
91
111
|
switch (spec.from) {
|
|
92
112
|
case "absent":
|
|
93
|
-
return { origin: spec, declared: false, read: () => observed(NONE), health: () => ({ state: "ok" }), onRead };
|
|
113
|
+
return { origin: credentialOriginOf(spec), declared: false, read: () => observed(NONE), health: () => ({ state: "ok" }), onRead };
|
|
94
114
|
case "env": {
|
|
95
115
|
const fixed = classify(spec.token, worker);
|
|
96
|
-
return { origin:
|
|
116
|
+
return { origin: credentialOriginOf(spec), declared: true, read: () => observed(fixed), health: () => ({ state: "ok" }), onRead };
|
|
97
117
|
}
|
|
98
118
|
case "file": {
|
|
99
119
|
const readFile = deps.readFile ?? ((p) => readFileSync(p, "utf8"));
|
|
@@ -111,7 +131,7 @@ export function createCenterCredentialSource(spec, worker, deps = {}) {
|
|
|
111
131
|
return readCredentialText(text, spec, worker, now());
|
|
112
132
|
};
|
|
113
133
|
return {
|
|
114
|
-
origin:
|
|
134
|
+
origin: credentialOriginOf(spec),
|
|
115
135
|
declared: true,
|
|
116
136
|
read() {
|
|
117
137
|
const r = readOnce();
|
package/dist/config-catalog.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { type RetiredEnvWire } from "@sema-agent/settings-schema";
|
|
|
2
2
|
import type { ServiceConfig, ServiceConfigGroups } from "./config-types.js";
|
|
3
3
|
import type { ConfigKnobRecord } from "./config.js";
|
|
4
4
|
import type { RestartSlice } from "./web-admin-client/restart-signal.js";
|
|
5
|
+
import { type EnvNameAllowlistKnob } from "./env-name-allowlist-knobs.js";
|
|
5
6
|
export declare const CATALOG_VALUE_TYPES: readonly ["boolean", "number", "string", "enum", "csv", "json", "path", "url", "secret", "opaque"];
|
|
6
7
|
export type CatalogValueType = (typeof CATALOG_VALUE_TYPES)[number];
|
|
7
8
|
export declare const CATALOG_TIMINGS: readonly ["hot", "restart", "deploy", "inert"];
|
|
@@ -19,15 +20,33 @@ export type CatalogDangerAxis = (typeof CATALOG_DANGER_AXES)[number];
|
|
|
19
20
|
export declare const URL_CREDENTIAL_POLICIES: readonly ["refuse", "mask"];
|
|
20
21
|
export type UrlCredentialPolicy = (typeof URL_CREDENTIAL_POLICIES)[number];
|
|
21
22
|
/**
|
|
22
|
-
* secret
|
|
23
|
-
* · `whole` —— 整值是一枚(令牌 / 口令 / 私钥 /
|
|
23
|
+
* secret 行的值**装着几枚本服务凭据、按什么读出来**(闭集;只在 `type: "secret"` 的行上,其余行恒缺席)—— 本服务凭据的颗粒按本服务读这只变量的那一只解析器定:
|
|
24
|
+
* · `whole` —— 整值是一枚(令牌 / 口令 / 私钥 / 一只模型密钥);
|
|
24
25
|
* · `token-table` —— `tok=system` 逗号表,每个 `tok` 是一枚(`SERVICE_AUTH_TOKENS`;读法 = `auth-keys.ts` `parseServiceAuthTokens`,`loadConfig` 同读);
|
|
25
|
-
* · `key-set` —— `{kid,key,status}` JSON 数组,每个 `key` 是一枚(`APPROVAL_HMAC_KEYS`;读法 = `auth-keys.ts` `parseApprovalHmacKeys`,`loadConfig` 同读)
|
|
26
|
-
*
|
|
27
|
-
*
|
|
26
|
+
* · `key-set` —— `{kid,key,status}` JSON 数组,每个 `key` 是一枚(`APPROVAL_HMAC_KEYS`;读法 = `auth-keys.ts` `parseApprovalHmacKeys`,`loadConfig` 同读);
|
|
27
|
+
* · `name-list` —— 零枚:原文是一张环境变量名单(名单型旋钮;读法 = `config.ts` `parseEnvNameAllowlist`)。名单不是凭据,原文不交引擎比值;
|
|
28
|
+
* 旋钮变量本身照按名扣(它的原文可能夹着被错展开进来的令牌,所以是 secret 行:目录只回在场位、名进自有凭据声明、不进任何子进程)。
|
|
29
|
+
* 读者只有一个:自有凭据声明的值臂(`server-secret-env.ts`)—— 交给引擎的恰是颗粒读出来的那几枚(列表形另把每一枚交出去 ⇒ 一枚令牌换了个变量名放着,与原变量同扣)。
|
|
30
|
+
* 词加一个而读者不补 ⇒ 编译红(读者是穷举 switch);secret 行不写 ⇒ 编译红(`r()` 的 secret 重载要它);哪只行取 `name-list` 由行名定类({@link SecretRowForm}),写反 ⇒ 编译红。不上 wire。
|
|
28
31
|
*/
|
|
29
|
-
export declare const SECRET_CREDENTIAL_FORMS: readonly ["whole", "token-table", "key-set"];
|
|
32
|
+
export declare const SECRET_CREDENTIAL_FORMS: readonly ["whole", "token-table", "key-set", "name-list"];
|
|
30
33
|
export type SecretCredentialForm = (typeof SECRET_CREDENTIAL_FORMS)[number];
|
|
34
|
+
/** 装着本服务凭据值的颗粒(`name-list` 以外的词):名单型旋钮以外的每条 secret 行、bake-runner 的凭据行都取其一。 */
|
|
35
|
+
export type CredentialValueForm = Exclude<SecretCredentialForm, "name-list">;
|
|
36
|
+
/**
|
|
37
|
+
* secret 行的颗粒**按行名定类**:名单型旋钮(闭集 `EnvNameAllowlistKnob`,叶表 `env-name-allowlist-knobs.ts` —— 「哪只变量是名单」只在那里写一次)恒 `name-list`,
|
|
38
|
+
* 其余恒是装着凭据值的颗粒。目录行写反(旋钮写 `whole`、凭据写 `name-list`)⇒ `r()` 的 secret 重载当场编译红 —— 列与旋钮闭集不会说两样。
|
|
39
|
+
*/
|
|
40
|
+
export type SecretRowForm<N extends string> = N extends EnvNameAllowlistKnob ? "name-list" : CredentialValueForm;
|
|
41
|
+
/**
|
|
42
|
+
* 配置目录**之外**的本包凭据变量:bake-runner 进程(构建宿主守护进程)自己读的凭据 —— 目录只装服务进程读的 env(D1 对账门把 `bake-runner/` 整只排除),
|
|
43
|
+
* runner 的键不是目录行,却是本包的自有凭据。自有凭据声明(`server-secret-env.ts`)把目录 secret 行与本表并成**一张**「名 → 颗粒」,三个进程入口
|
|
44
|
+
* (stage-01 / run-local / bake-runner)同读这一份(不按「归谁消费」切):名全声明,值按颗粒逐枚交引擎 ⇒ 名单型旋钮点到它(名是或值是)拒启、任何宿主腿都不交它与它的副本。
|
|
45
|
+
* 读点 `bake-runner/main.ts` `loadEnv` 按本表的键读(键改名而读点不跟 ⇒ 编译红)。不上 wire,不进 `GET /v1/config/catalog`。
|
|
46
|
+
*/
|
|
47
|
+
export declare const BAKE_RUNNER_CREDENTIAL_ENV: {
|
|
48
|
+
readonly BAKE_RUNNER_TOKEN: "whole";
|
|
49
|
+
};
|
|
31
50
|
/** 域 = 配置九组(类型锁步:组集变了这里跟着红)。 */
|
|
32
51
|
export type CatalogDomain = keyof ServiceConfigGroups;
|
|
33
52
|
export declare const CATALOG_RESTART_SLICES: readonly RestartSlice[];
|
|
@@ -103,7 +122,7 @@ export interface ConfigCatalogSpec {
|
|
|
103
122
|
readonly scope?: "bootstrap-only";
|
|
104
123
|
/** url 行的凭据处置披露({@link UrlCredentialPolicy});url 行必填(`r()` 的 url 重载要它,缺 ⇒ 编译红),其余行写不进来。 */
|
|
105
124
|
readonly credentialPolicy?: UrlCredentialPolicy;
|
|
106
|
-
/** secret 行的凭据颗粒({@link SecretCredentialForm});secret 行必填(`r()` 的 secret 重载要它,缺 ⇒
|
|
125
|
+
/** secret 行的凭据颗粒({@link SecretCredentialForm});secret 行必填(`r()` 的 secret 重载要它,缺 ⇒ 编译红;取哪一类按行名定 —— {@link SecretRowForm}),其余行写不进来。 */
|
|
107
126
|
readonly credentialForm?: SecretCredentialForm;
|
|
108
127
|
}
|
|
109
128
|
export interface ConfigCatalogRowCenter {
|
package/dist/config-catalog.js
CHANGED
|
@@ -28,7 +28,8 @@ export const CATALOG_VALUE_TYPES = ["boolean", "number", "string", "enum", "csv"
|
|
|
28
28
|
export const CATALOG_TIMINGS = ["hot", "restart", "deploy", "inert"];
|
|
29
29
|
export const CATALOG_DANGER_AXES = ["security", "billing", "data"];
|
|
30
30
|
export const URL_CREDENTIAL_POLICIES = ["refuse", "mask"];
|
|
31
|
-
export const SECRET_CREDENTIAL_FORMS = ["whole", "token-table", "key-set"];
|
|
31
|
+
export const SECRET_CREDENTIAL_FORMS = ["whole", "token-table", "key-set", "name-list"];
|
|
32
|
+
export const BAKE_RUNNER_CREDENTIAL_ENV = { BAKE_RUNNER_TOKEN: "whole" };
|
|
32
33
|
const RESTART_SLICE_SET = {
|
|
33
34
|
skills: true,
|
|
34
35
|
mcp: true,
|
|
@@ -70,7 +71,7 @@ export const CONFIG_CATALOG = [
|
|
|
70
71
|
r("ADOPTION_IMPORT_MAX_SESSIONS", "limitsHttp", "number", `收编批量导入 POST /v1/adoption/:id/sessions 每请求最多几个会话信封(超了整请求 400 request.field_invalid,句子点名本旋钮;地板 ${ADOPTION_IMPORT_MAX_SESSIONS_FLOOR},越界夹取 + 点名,小数拒启);当前值经能力位 adoptionImport.maxSessions 交给已收编的源主体`, { staticDefault: String(ADOPTION_IMPORT_MAX_SESSIONS_DEFAULT), configKey: "adoptionImportMaxSessions" }),
|
|
71
72
|
r("ADOPTION_IMPORT_MAX_SESSION_BYTES", "limitsHttp", "number", `收编批量导入每个会话信封最多多少字节(信封 JSON 的 UTF-8 字节;超了只拒那一个元素 rejected/too_large,带 count 与 cap;合法域 [${ADOPTION_IMPORT_MAX_SESSION_BYTES_FLOOR}, ${ADOPTION_IMPORT_MAX_SESSION_BYTES_CEILING}] —— 上帽 = JSON 体上限减空批包络,再大的值够不着,越界夹取 + 点名,小数拒启);当前值经能力位 adoptionImport.maxSessionBytes 交给已收编的源主体`, { staticDefault: String(ADOPTION_IMPORT_MAX_SESSION_BYTES_DEFAULT), configKey: "adoptionImportMaxSessionBytes" }),
|
|
72
73
|
r("AGENT_DATA_DIR", "store", "path", "本机数据根回落链一环(LOCAL_DATA_ROOT → CONFIG_LOCAL_DIR → AGENT_DATA_DIR → ~/.ai-agent);记忆引擎缺省根同链", { danger: DATA, derivedDefaultNote: "缺席 ⇒ 链上下一环,最终 ~/.ai-agent" }),
|
|
73
|
-
r("ALLOW_UNAUTHED_WRITES", "auth", "boolean", "
|
|
74
|
+
r("ALLOW_UNAUTHED_WRITES", "auth", "boolean", "写门对没带过门凭据(service token / 鉴权桥验过的登录令牌)的请求也放行:任务提交、改写门与破坏性会话写都照收(本地开发逃生口;缺省 fail-closed 拒)", { staticDefault: "false", danger: SEC, configKey: "allowUnauthedWrites" }),
|
|
74
75
|
r("ANTHROPIC_API_KEY", "modelPlane", "secret", "Anthropic 协议路线的 x-api-key 凭据(只发 x-api-key 头;与 ANTHROPIC_AUTH_TOKEN 互斥 —— 同设拒启,机读码 `config.anthropic_credential_conflict`;与 BASE_URL 同在时可推断 provider)", { credentialForm: "whole", danger: [...SEC, ...BILL] }),
|
|
75
76
|
r("ANTHROPIC_AUTH_TOKEN", "modelPlane", "secret", "Anthropic 兼容生态的 Bearer 凭据(只发 Authorization: Bearer 头;与 ANTHROPIC_API_KEY 互斥 —— 同设拒启,机读码 `config.anthropic_credential_conflict`)", { credentialForm: "whole", danger: [...SEC, ...BILL] }),
|
|
76
77
|
r("ANTHROPIC_BASE_URL", "modelPlane", "url", "Anthropic 协议路线 base URL(与凭据同在且 MODEL_PROVIDER 未设 ⇒ 推断 provider=anthropic 并 boot notice;带 userinfo 拒启,机读码 `config.gateway_url_userinfo`;解析不动/不透明形拒启,机读码 `config.model_route_url_invalid`;带 `#fragment` 拒启,机读码 `config.model_route_url_fragment` —— fragment 从不上线,后缀会落进被丢弃的那一半)", { credentialPolicy: "refuse" }),
|
|
@@ -94,7 +95,7 @@ export const CONFIG_CATALOG = [
|
|
|
94
95
|
r("AUTH_BRIDGE_AUDIENCE", "auth", "string", "registry SSO-JWT 验签期望 aud", { danger: SEC }),
|
|
95
96
|
r("AUTH_BRIDGE_ISSUER", "auth", "url", "registry SSO-JWT issuer(auth bridge 的开关之一;**不是**托管证据 —— 多租户只认 REQUIRE_PRINCIPAL=true)", { credentialPolicy: "mask", danger: SEC, derivedDefaultNote: "缺席 ⇒ 桥的装配处回退到 webAdmin.baseUrl(配了 center 即默认开桥);显式值与回退值在托管判定上同判(都不算)", configKey: "authBridgeIssuer" }),
|
|
96
97
|
r("AUTH_BRIDGE_JWKS_URL", "auth", "url", "registry SSO-JWT 的 JWKS 地址(缺省从 issuer 派生)", { credentialPolicy: "mask", danger: SEC }),
|
|
97
|
-
r("AUTONOMY", "auth", "enum", "运维 autonomy 模式(read-only ⇒ 只读手 + 写面 roots,每段续跑重折,子代同受、委派照挂;ask ⇒ 恒 shellGate,每段重折;plan ⇒ 提交入口的模式词地板:新提交的任务以 permissionMode:plan 起步,请求词钳到它之下,写与非只读调用在调用时问 / 拒,批准计划之后整条 run 按批准的档跑完);center 腿热且 non-sticky(plan
|
|
98
|
+
r("AUTONOMY", "auth", "enum", "运维 autonomy 模式(read-only ⇒ 只读手 + 写面 roots,每段续跑重折,子代同受、委派照挂;ask ⇒ 恒 shellGate,每段重折;plan ⇒ 提交入口的模式词地板:新提交的任务以 permissionMode:plan 起步,请求词钳到它之下,写与非只读调用在调用时问 / 拒,批准计划之后整条 run 按批准的档跑完);center 腿热且 non-sticky(plan 地板作用于之后的提交,也作用于停驻 run 的下一次续跑:续跑之前体上的词过此刻的地板,批准计划写下的档原样)", { danger: SEC, enumValues: AUTONOMY_MODES, configKey: "autonomy", center: cGov("autonomy") }),
|
|
98
99
|
r("AUTO_BACKGROUND_ON_TIMEOUT", "orchestration", "boolean", "前台 Bash 命令撞上它自己的超时时:开 ⇒ 合格的命令(资格由引擎判)转成后台任务继续跑(后台进程上限与后台超时硬上限照常管它);同一个开关也让引擎在有人的输入排队等着而合格命令还在跑时把它转后台、好让输入送达;关 ⇒ 两件都不做,超时即杀。只在能把运行中的命令领养成后台的车道上生效,其余车道照起、旋钮不生效 —— 本车道上生不生效看 GET /health 的 autoBackgroundOnTimeout(armed / off / unsupported)", { staticDefault: "true", configKey: "autoBackgroundOnTimeout" }),
|
|
99
100
|
r("AUTO_MODE_CLASSIFIER_FALLBACK", "approval", "enum", "auto 分类器席答不出裁决时的梯子(main=主模型代判 / none=只留分类器那一级,整条拒)", { enumValues: ["main", "none"], danger: SEC, derivedDefaultNote: "未设/空串 ⇒ 不铸键,跟随引擎缺省 main(core 7.18.0 起;空串按未设,与其余词表旋钮同判);none = 7.77.0 及以前的行为逐字;词表外的值启动期拒启。权限轴放宽,升级须知见 DEPLOY-PREREQS", configKey: "autoModeClassifierFallback" }),
|
|
100
101
|
r("AUTO_MODE_CLASSIFIER_TIMEOUT_MS", "approval", "number", `auto 分类器单级判决上限(ms;缺席 = core 缺省;自托管慢网关按排队 + prefill 留足;一级到点没裁 ⇒ 走下一级,走完仍没裁 ⇒ 这次门控调用整条拒;须为 [${AUTO_MODE_CLASSIFIER_TIMEOUT_BOUNDS.minMs}, ${AUTO_MODE_CLASSIFIER_TIMEOUT_BOUNDS.maxMs}] 内十进制整数,0 / 小数 / 越界拒启)`, { derivedDefaultNote: "未设/空串 ⇒ 不铸键,跟随 core 缺省(本仓不复制上游数字;core 改缺省本旋钮照映不改)", configKey: "autoModeClassifierTimeoutMs" }),
|
|
@@ -106,7 +107,7 @@ export const CONFIG_CATALOG = [
|
|
|
106
107
|
r("BAKE_SUBMIT_RATE_MAX", "orchestration", "number", "per-principal bake 提交限流窗内最大次数(0=关)", { staticDefault: "10" }),
|
|
107
108
|
r("BAKE_SUBMIT_RATE_WINDOW_SEC", "orchestration", "number", "per-principal bake 提交限流窗长(秒)", { staticDefault: "60" }),
|
|
108
109
|
r("BG_AGENT_PARK_CLAIM_STALE_MS", "orchestration", "number", "parked 后台 agent 的 stale-claim 清算窗(ms;claimer 崩死的行由此解卡)", { staticDefault: String(60 * 60_000), configKey: "backgroundAgentParkClaimStaleMs" }),
|
|
109
|
-
r("BG_AGENT_RETENTION_MS", "orchestration", "number", "TERMINAL 后台 agent
|
|
110
|
+
r("BG_AGENT_RETENTION_MS", "orchestration", "number", "保留期(ms)的两个读者:TERMINAL 后台 agent 行(终局起,reaper 按 scope 清)与 sidechain 会话(最后活动起,维护拍的会话老化腿删)", { staticDefault: String(7 * 24 * 60 * 60 * 1000), danger: DATA, configKey: "backgroundAgentRetentionMs" }),
|
|
110
111
|
r("BG_AGENT_STALE_RUNNING_MS", "orchestration", "number", "running 后台 agent 行写者心跳断更超此值翻 failed(ms;下限 10min 硬钳)", { staticDefault: String(15 * 60_000), configKey: "backgroundAgentStaleRunningMs" }),
|
|
111
112
|
r("BG_AGENT_STALL_MS", "orchestration", "number", "会话驻留后台子代理的停滞收割窗(ms;最后一次工具活动距今超此值 ⇒ 行收成 killed、归因 system、run 中止;缺省 = 下限,只许拉大,无关闭档)", { derivedDefaultNote: "缺席 ⇒ max(600000, max(STREAM_ASK_WINDOW_MS, UNREACHED_ASK_TTL_MS, QUESTION_TTL_MS, MCP_ELICITATION_TTL_MS) + 引擎单命令上限(缺省 600000));单用户 posture 下 86400000 + 600000", configKey: "backgroundAgentStallMs" }),
|
|
112
113
|
r("BIND_HOST", "auth", "string", "监听绑址(显式值恒生效)", { danger: SEC, derivedDefaultNote: "缺席:无鉴权写面(allowUnauthedWrites ∧ 零凭证)自动收窄 127.0.0.1,其余全接口", resolve: (c) => c.bindHost ?? null }),
|
|
@@ -152,7 +153,7 @@ export const CONFIG_CATALOG = [
|
|
|
152
153
|
r("DOCKER_NETWORK", "orchestration", "enum", "local-docker 容器网络模式", { enumValues: ["none", "bridge", "host"], staticDefault: "bridge", danger: SEC }),
|
|
153
154
|
r("DOCKER_PATH", "orchestration", "path", "docker 二进制路径"),
|
|
154
155
|
r("DOCKER_PIDS_LIMIT", "orchestration", "number", "local-docker fork-bomb 背栓(--pids-limit;非法值回 adapter 默认 512+warn)", { danger: SEC, derivedDefaultNote: "缺席 ⇒ adapter 默认 512" }),
|
|
155
|
-
r("DOCKER_SANDBOX_ENV", "orchestration", "secret", "local-docker 车道每条 docker exec 以 -e 注入的本进程 env 点名表(NAME,NAME;点到的键从 worker env 原样取,值不进 spec/center/日志;与 LSP_ENV_ALLOW / E2B_SANDBOX_ENV 同一只解析器与「点名放行」谓词:形错 / 点名名单型旋钮 / 点名本服务自有凭据 —— 名是,或值是本服务的某一枚凭据(另一个名下的副本)—— (会把本服务的凭据装进模型读得到的沙箱;判官 = 引擎此刻的自有凭据声明)拒启且不回显值;本进程环境里没有的名按序号 warn、不转发;只在本车道被选中时求值;原文按凭据类对待:只回在场位、不进任何子进程)", { credentialForm: "
|
|
156
|
+
r("DOCKER_SANDBOX_ENV", "orchestration", "secret", "local-docker 车道每条 docker exec 以 -e 注入的本进程 env 点名表(NAME,NAME;点到的键从 worker env 原样取,值不进 spec/center/日志;与 LSP_ENV_ALLOW / E2B_SANDBOX_ENV 同一只解析器与「点名放行」谓词:形错 / 点名名单型旋钮 / 点名本服务自有凭据 —— 名是,或值是本服务的某一枚凭据(另一个名下的副本)—— (会把本服务的凭据装进模型读得到的沙箱;判官 = 引擎此刻的自有凭据声明)拒启且不回显值;本进程环境里没有的名按序号 warn、不转发;只在本车道被选中时求值;原文按凭据类对待:只回在场位、不进任何子进程)", { credentialForm: "name-list", danger: SEC }),
|
|
156
157
|
r("DRAIN_GRACE_MS", "limitsHttp", "number", "SIGTERM 优雅排空窗(ms;期间新计费提交 503+Retry-After)。出厂默认是**服务器部署**的取值;壳自 spawn 的引擎会被壳注入更短的窗 ⇒ 排壳形关机预算时按壳自己注入的值算(壳读不到本目录:它是 operator-only),排空开始后本次排空定死的到期点读 GET /health 的 engineSignal.draining.deadlineAt,从信号到进程退出的上界见 USAGE 的「停机上界(契约句)」;不照抄 staticDefault", { staticDefault: String(10 * 60 * 1000), configKey: "drainGraceMs", center: cLimits("drainGraceMs") }),
|
|
157
158
|
r("DRAIN_SECOND_SIGNAL_MIN_GAP_MS", "limitsHttp", "number", `排空期「第二发信号 = 硬停」的最小间隔(ms;锚 = 本次排空的第一发停止信号 —— SIGTERM / SIGHUP 升级进的排空,入口那一发就是它;排空口 / 租约被拒 / 附着租约自退进的排空,到达的第一发被吸收、不缩短期限。SIGTERM / SIGINT 与锚相隔不足 ⇒ 同一拍的重复投递,一行 drain_duplicate_signal_ignored 后忽略、排空继续;0 = 关,恒按第二发硬停;须为 [${DRAIN_SECOND_SIGNAL_MIN_GAP_BOUNDS.minMs}, ${DRAIN_SECOND_SIGNAL_MIN_GAP_BOUNDS.maxMs}] 内十进制整数(上界 = DRAIN_GRACE_MS 地板),小数 / 负数 / 越界拒启)`, { staticDefault: String(DRAIN_SECOND_SIGNAL_MIN_GAP_DEFAULT_MS), configKey: "drainSecondSignalMinGapMs" }),
|
|
158
159
|
r("DURABLE_APPROVAL", "approval", "boolean", "durable suspend/resume HITL(需 SQL 店;决定 checkpointStore 与 /v1/approvals 面的存在性)", { danger: SEC, derivedDefaultNote: "posture 三态:显式词恒赢,缺席 = 单用户(REQUIRE_PRINCIPAL≠true)且有耐久店 ⇒ on / 多租户或无耐久店 ⇒ off;生效来源见 GET /v1/diagnostics/wiring 的 serverGates.durableApproval.source", configKey: "durableApproval" }),
|
|
@@ -164,7 +165,7 @@ export const CONFIG_CATALOG = [
|
|
|
164
165
|
r("E2B_LIVENESS_MS", "orchestration", "number", LIVENESS_KNOB_SEMANTICS("e2b"), { derivedDefaultNote: LIVENESS_KNOB_DEFAULT_NOTE }),
|
|
165
166
|
r("E2B_MOUNT_PATH", "orchestration", "path", "e2b 工作区根(resume 用当前值,改前先 drain 挂起任务)"),
|
|
166
167
|
r("E2B_ORPHAN_RECLAIM", "orchestration", "boolean", "崩溃遗留沙盒回收腿(boot 一次+周期;判据保守,拿不准恒不杀)", { staticDefault: "true", danger: BILL }),
|
|
167
|
-
r("E2B_SANDBOX_ENV", "orchestration", "secret", "转发进 e2b 沙箱的本进程 env 点名表(NAME,NAME;点到的键从 worker env 原样取,值不进 spec/center/事件日志;与 LSP_ENV_ALLOW / DOCKER_SANDBOX_ENV 同一只解析器与「点名放行」谓词:形错 / 点名名单型旋钮 / 点名本服务自有凭据 —— 名是,或值是本服务的某一枚凭据(另一个名下的副本)—— (会把本服务的凭据装进模型读得到的沙箱;判官 = 引擎此刻的自有凭据声明)拒启且不回显值;本进程环境里没有的名按序号 warn、不转发;只在本车道被选中时求值;原文按凭据类对待:只回在场位、不进任何子进程)", { credentialForm: "
|
|
168
|
+
r("E2B_SANDBOX_ENV", "orchestration", "secret", "转发进 e2b 沙箱的本进程 env 点名表(NAME,NAME;点到的键从 worker env 原样取,值不进 spec/center/事件日志;与 LSP_ENV_ALLOW / DOCKER_SANDBOX_ENV 同一只解析器与「点名放行」谓词:形错 / 点名名单型旋钮 / 点名本服务自有凭据 —— 名是,或值是本服务的某一枚凭据(另一个名下的副本)—— (会把本服务的凭据装进模型读得到的沙箱;判官 = 引擎此刻的自有凭据声明)拒启且不回显值;本进程环境里没有的名按序号 warn、不转发;只在本车道被选中时求值;原文按凭据类对待:只回在场位、不进任何子进程)", { credentialForm: "name-list", danger: SEC }),
|
|
168
169
|
r("E2B_SANDBOX_MAX_MS", "orchestration", "number", "e2b 沙箱最长存活(ms)", { staticDefault: "3600000", danger: BILL }),
|
|
169
170
|
r("E2B_TEMPLATE", "orchestration", "string", "e2b 模板名(缺省 adapter 基础模板)"),
|
|
170
171
|
r("E2B_TIMEOUT_MS", "orchestration", "number", "e2b 单命令总超时(ms)"),
|
|
@@ -177,10 +178,10 @@ export const CONFIG_CATALOG = [
|
|
|
177
178
|
r("FILE_HISTORY_CAPTURE", "store", "boolean", "文件历史**捕获**总开关(三条车道同义)。关 = 不再捕获任何改动文件的首次快照(落 core 的部署捕获位 `RunnerDeps.fileHistoryCapture: \"off\"`,能力词 `fileHistoryCapture` 翻 off);7.104.0 起**只关捕获**:历史店照接,已存历史照常 restoreFiles / rewindFilesTo / 2c session-sync。关掉 ≠ 删掉:已捕获的历史不被批量删除,仍按会话删除与留存规则清理 —— 要清存量走 DELETE 会话或留存旋钮;没有「整库历史不可用」的旋钮", { staticDefault: "true", danger: DATA, configKey: "fileHistoryCapture" }),
|
|
178
179
|
r("FILE_HISTORY_RETENTION_KEEP", "store", "number", "per-file rewind 历史的保留上限(与 core FileStorageBackend 同域键形,三条车道一套语义)", { danger: DATA, derivedDefaultNote: "缺席 ⇒ core 缺省 100" }),
|
|
179
180
|
r("FLEET_ADVERTISE_ADDRESS", "integrations", "url", `fleet 面向 center 公告的本 worker 可达地址(中心车道配齐 + 本键 ⇒ 公告环;空串 = 未设;用量环不看本键)。中心往它后面拼路径,与中心基址三席同一条判据:${CENTER_BASE_URL_RULE}`, { credentialPolicy: "refuse", configKey: "fleetAdvertiseAddress" }),
|
|
180
|
-
r("FLEET_GENERATION", "integrations", "string", "fleet 成员的代际(配置渲染器写;引擎回声到心跳与 /health 的 generation)。缺席 ⇔ 非 fleet 成员(
|
|
181
|
+
r("FLEET_GENERATION", "integrations", "string", "fleet 成员的代际(配置渲染器写;引擎回声到心跳与 /health 的 generation)。缺席 ⇔ 非 fleet 成员(不续服务租约、不受围栏、sso 准入不比对令牌 scope;成员上令牌 scope 必须等于 FLEET_SCOPE);在场必须是规范十进制串(\"0\" / \"7\";空串、前导零、符号、空白拒启)", { danger: SEC, configKey: "fleetGeneration" }),
|
|
181
182
|
r("FLEET_LEASE_FAIL_CLOSED", "integrations", "boolean", "租约连接级失败(中心鉴权拒 / 凭证不可读 / 不可达 / 5xx / 超时 / 坏体)时计费入口拒 503 fleet.lease_unavailable(true)还是放行(false);409 not-lease 与耗尽 429 不受它管;词表外拒启", { danger: SEC, derivedDefaultNote: "缺席 ⇒ 按部署姿态派生:REQUIRE_PRINCIPAL=true ⇒ true(多租:额度是安全轴);单用户 ⇒ false(AP 姿态)。显式值压过派生。生效值见 caps centerWiring.failMode", configKey: "fleetLeaseFailClosed" }),
|
|
182
183
|
r("FLEET_LEASE_OUTAGE_MAX_MS", "integrations", "number", "一台实例「活着而不服务」的最长时长 T_max(ms),两处读它:① 服务租约中心不可达的容忍上限 —— 租约过期(从没被授予过的:从围栏生效那一刻;一直没听到中心的成员从本进程起点)满这么久 ⇒ 新计费提交 503 state.lease_expired(取消 / HITL 应答 / 续跑 / 读面照放行,在飞不动,/readyz 不翻),只在 fleet 成员 ∧ 中心没有声明不执行租约(心跳答复的 capabilities 声明不带 servingLease)时生效;② 排空口 POST /v1/admin/drain 的期限上界 —— deadlineAt 离此刻超过它 ⇒ 400 request.field_invalid,成员与非成员同读;< 60000(租约 TTL 地板)或非整数拒启", { danger: SEC, staticDefault: String(FLEET_LEASE_OUTAGE_MAX_DEFAULT_MS), configKey: "fleetLeaseOutageMaxMs" }),
|
|
183
|
-
r("FLEET_SCOPE", "integrations", "string", "本引擎所在的租户 scope(配置渲染器对每台受管引擎写,缺省 scope 也写;手接的引擎缺席 = 缺省 scope
|
|
184
|
+
r("FLEET_SCOPE", "integrations", "string", "本引擎所在的租户 scope(配置渲染器对每台受管引擎写,缺省 scope 也写;手接的引擎缺席 = 缺省 scope;两个读者读同一个值:排空口 POST /v1/admin/drain 的身份比对(请求不带 scope 也读成缺省 scope)与 fleet 成员(FLEET_GENERATION 在场)上的 sso 准入 —— 登记中心登录令牌的 scope ≠ 本值 ⇒ 整次请求 403 auth.scope_mismatch;非成员不比对)。在场必须是 scope id 形(小写字母 / 数字 / 内部连字符,1–64;空串拒启);与 FLEET_GENERATION 不联动(成员缺席 ⇒ 缺省 scope)。续租体与心跳不带它(scope 由中心凭证绑定)", { danger: SEC, staticDefault: GLOBAL_SCOPE, configKey: "fleetScope" }),
|
|
184
185
|
r("FORK_ENABLED", "orchestration", "boolean", "CC /fork(core Fork 工具)装配开关", { derivedDefaultNote: "posture 三态:缺席 = 单用户 ⇒ on / 多租户 ⇒ off(per-principal entitlement 另判)", configKey: "forkEnabled" }),
|
|
185
186
|
r("GATEWAY_MAX_RETRIES", "modelPlane", "number", "openai 兼容腿每次调用重试上限", {
|
|
186
187
|
derivedDefaultNote: "缺席 ⇒ 按外层拓扑分两态(启动日志 `brain` 字段的 `gatewayRetryCap` 回显哪一态):配了备用网关(`MODEL_GATEWAY_FALLBACK_URLS`)/ 开了断路器开关(`MODEL_CIRCUIT_BREAKER`,单路网关上也算)/ 开了反应式降级(配着 `MODEL_DEGRADE_TO` 且 `MODEL_DEGRADE_REACTIVE` 开)" +
|
|
@@ -191,7 +192,7 @@ export const CONFIG_CATALOG = [
|
|
|
191
192
|
r("GIT_API_KIND", "integrations", "enum", "Git host API 方言", { enumValues: ["gitea", "github"], staticDefault: "gitea", configKey: "gitApiKind" }),
|
|
192
193
|
r("GIT_API_TOKEN", "integrations", "secret", "repo 工具的 Git host 凭据", { credentialForm: "whole", danger: SEC }),
|
|
193
194
|
r("HOOKS_TIMEOUT_MS", "orchestration", "number", "请求 hooks 的每张车道注册(settings.hooks / settings.hooks.managed,各一份同值)每个 handler 的时间预算(ms;0=零预算是合法值)", { derivedDefaultNote: "缺席 ⇒ 不铸键,读法 settingsHooksBudgetMs 取 600000" }),
|
|
194
|
-
r("HOOK_ENV_ALLOW", "orchestration", "secret", `settings hook 环境的点名放回名单(点到的键从服务进程环境原样放回 hook 环境、部署方显式承担:命令 hook 的子进程 env 与 http hook 头的 $NAME 插值读同一份;服务进程变量进 hook 环境只有这一个来源,请求的 allowedEnvVars / settings.httpHookAllowedEnvVars 只收窄、不授予;形错 / 点名任一只名单型旋钮(含自己)/ 点名本服务自有凭据 —— 名是,或值是本服务的某一枚凭据(另一个名下的副本;列表形凭据逐枚比)—— (判官 = 引擎此刻的自有凭据声明)拒启且不回显值;本进程环境里没有的名按序号 warn、不放回、不回显;多租户姿态(忽略时起服 warn 一次):${describeAllowlistPostures()};原文按凭据类对待:只回在场位、不进任何子进程)`, { credentialForm: "
|
|
195
|
+
r("HOOK_ENV_ALLOW", "orchestration", "secret", `settings hook 环境的点名放回名单(点到的键从服务进程环境原样放回 hook 环境、部署方显式承担:命令 hook 的子进程 env 与 http hook 头的 $NAME 插值读同一份;服务进程变量进 hook 环境只有这一个来源,请求的 allowedEnvVars / settings.httpHookAllowedEnvVars 只收窄、不授予;形错 / 点名任一只名单型旋钮(含自己)/ 点名本服务自有凭据 —— 名是,或值是本服务的某一枚凭据(另一个名下的副本;列表形凭据逐枚比)—— (判官 = 引擎此刻的自有凭据声明)拒启且不回显值;本进程环境里没有的名按序号 warn、不放回、不回显;多租户姿态(忽略时起服 warn 一次):${describeAllowlistPostures()};原文按凭据类对待:只回在场位、不进任何子进程)`, { credentialForm: "name-list", danger: SEC, derivedDefaultNote: "缺席 / 空串 ⇒ 空名单 = 不放回(hook 环境 = 十二名基础名单 + 请求 settings.env)" }),
|
|
195
196
|
r("HOST_BG_DEFAULT_TIMEOUT_SEC", "orchestration", "number", "host 后台 shell 缺省超时(秒)", { staticDefault: "300" }),
|
|
196
197
|
r("HOST_BG_ENABLED", "orchestration", "boolean", "host 车道后台 shell 开关", { staticDefault: "true" }),
|
|
197
198
|
r("HOST_BG_FILE_CAP", "orchestration", "number", "host 后台 shell 磁盘护栏(字节;失控输出被 reap)", { staticDefault: String(64 * 1024 * 1024) }),
|
|
@@ -227,7 +228,7 @@ export const CONFIG_CATALOG = [
|
|
|
227
228
|
r("K8S_NAMESPACE", "orchestration", "string", "沙箱 pod 所在的 namespace(REMOTE_EXEC=k8s 必需件,与 K8S_SANDBOX_IMAGE 同级:缺席、空串或只有空白 ⇒ 起服拒,拒句点名本旋钮;服务不带内置缺省 —— 部署的声明是唯一来源,随包 chart 已显式设为 sandbox.namespace;只在 REMOTE_EXEC=k8s 被选中时求值)"),
|
|
228
229
|
r("K8S_RUNTIME_CLASS", "orchestration", "string", "沙箱 pod runtimeClass(Kata 等)"),
|
|
229
230
|
r("K8S_SANDBOX_BROKER_IMAGE", "orchestration", "string", "成员 git 凭据代理容器的镜像(k8s 沙箱 pod 的 containers[1],只挂在成员 run 的 pod 上;建议填本引擎自身镜像 —— 代理是本包里固定路径的一只程序,命令固定);不设 ⇒ 成员 git 凭据平面关(GET /v1/capabilities 的 credentialPlane.sandboxGit = broker_image_unset),任何 pod 都不挂代理,pod 形逐字节同不设时;只在 REMOTE_EXEC=k8s 被选中时求值"),
|
|
230
|
-
r("K8S_SANDBOX_ENV", "orchestration", "secret", `转发进 k8s 沙箱 pod 容器 env 的本进程 env 点名表(NAME,NAME;点到的键从 worker env 原样取,值只进该 pod 自己的 Secret —— pod spec 的容器 env 只带 secretKeyRef 引用、不带值,Secret 随 pod 由集群回收;不进工作区 / 快照 / center / 事件日志;沙箱命名空间的 Role 要 secrets ${SANDBOX_SECRET_SEAT_VERBS.env.join(" / ")},起服问不许即拒启;与 LSP_ENV_ALLOW / E2B_SANDBOX_ENV / DOCKER_SANDBOX_ENV 同一只解析器与「点名放行」谓词:形错 / 点名名单型旋钮 / 点名本服务自有凭据 —— 名是,或值是本服务的某一枚凭据(另一个名下的副本)—— (会把本服务的凭据装进模型读得到的沙箱;判官 = 引擎此刻的自有凭据声明)拒启且不回显值;本进程环境里没有的名按序号 warn、不转发;与包源派生 env 撞名时显式名单胜;只在本车道被选中时求值;原文按凭据类对待:只回在场位、不进任何子进程)`, { credentialForm: "
|
|
231
|
+
r("K8S_SANDBOX_ENV", "orchestration", "secret", `转发进 k8s 沙箱 pod 容器 env 的本进程 env 点名表(NAME,NAME;点到的键从 worker env 原样取,值只进该 pod 自己的 Secret —— pod spec 的容器 env 只带 secretKeyRef 引用、不带值,Secret 随 pod 由集群回收;不进工作区 / 快照 / center / 事件日志;沙箱命名空间的 Role 要 secrets ${SANDBOX_SECRET_SEAT_VERBS.env.join(" / ")},起服问不许即拒启;与 LSP_ENV_ALLOW / E2B_SANDBOX_ENV / DOCKER_SANDBOX_ENV 同一只解析器与「点名放行」谓词:形错 / 点名名单型旋钮 / 点名本服务自有凭据 —— 名是,或值是本服务的某一枚凭据(另一个名下的副本)—— (会把本服务的凭据装进模型读得到的沙箱;判官 = 引擎此刻的自有凭据声明)拒启且不回显值;本进程环境里没有的名按序号 warn、不转发;与包源派生 env 撞名时显式名单胜;只在本车道被选中时求值;原文按凭据类对待:只回在场位、不进任何子进程)`, { credentialForm: "name-list", danger: SEC }),
|
|
231
232
|
r("K8S_SANDBOX_IMAGE", "orchestration", "string", "k8s 车道沙箱镜像(REMOTE_EXEC=k8s 必需件)"),
|
|
232
233
|
r("K8S_SANDBOX_IPV6", "orchestration", "enum", "k8s 沙箱 pod 的 IPv6:disabled = pod 级 sysctl 关 IPv6(net.ipv6.conf.all / default.disable_ipv6=1;两只都不在 k8s 的 safe sysctl 表里 ⇒ 每个节点 kubelet 要 --allowed-unsafe-sysctls 点名,否则 pod 起不来;沙箱 ns 不能 enforce PodSecurity baseline / restricted);enabled = 不动 pod(pod 保留平台给的 IPv6,只执行 IPv4 的出网策略管不到它,起服自检每次一行 sandbox_egress_policy_gap{kind: ipv6_enabled});词表外拒启", { enumValues: SANDBOX_IPV6_WORDS, staticDefault: SANDBOX_IPV6_DEFAULT, danger: SEC }),
|
|
233
234
|
r("K8S_TIMEOUT_MS", "orchestration", "number", "k8s 沙箱 pod 寿命(activeDeadlineSeconds,ms;整只 pod 的泄漏护栏,后台任务超时也被它钳;各条命令的超时见工具超时)"),
|
|
@@ -253,7 +254,7 @@ export const CONFIG_CATALOG = [
|
|
|
253
254
|
r("LOCAL_STORE_DURABILITY", "store", "enum", "运维声明 local 店易失(词闭集只有 ephemeral):local 后端交给会话店与检查点店两半的引擎声明都降为 process-local(委派分区不降:后台子代照旧能停驻) ⇒ 数据根落在易失介质(容器可写层 / tmpfs / emptyDir)上不再拒启 config.store_not_durable,起服 warn 一行;后果 = 店里的会话、停驻审批与记忆不随容器 / Pod 替换保留(进程重启照旧活过)。读面 store.durability 照旧按介质如实报。SQL / memory 后端不读。部署者自己设,壳 / 编排器不代写", { enumValues: LOCAL_STORE_DECLARATION_WORDS, danger: DATA, derivedDefaultNote: "缺席 ⇒ 店型的设计声明(活过进程重启);店落在调用方自己的盘上(host 车道单主)且数据根介质易失时,同样降为 process-local", configKey: "localStoreDurability" }),
|
|
254
255
|
r("LOCKED_CONFIG_KEYS", "auth", "csv", "管理员锁定层声明(词表=core 闭集注册表,未知键拒启)", { danger: SEC, configKey: "lockedConfigKeys" }),
|
|
255
256
|
r("LOG_LEVEL", "observability", "string", "日志档位", { staticDefault: "info", configKey: "logLevel" }),
|
|
256
|
-
r("LSP_ENV_ALLOW", "orchestration", "secret", `host 腿语言服务器子进程 env 的点名放行名单(点到的键从服务 env 原样放回、部署方显式承担;没点到的照剥;与 host shell inheritEnv:[names] 同一只谓词;形错 / 点名任一只名单型旋钮(含自己)/ 点名本服务自有凭据 —— 名是,或值是本服务的某一枚凭据(另一个名下的副本)—— (剥后放回会把引擎刚扣下的凭据交回去;判官 = 引擎此刻的自有凭据声明)拒启且不回显值;本进程环境里没有的名按序号 warn、不放行、不回显;多租户姿态(忽略时起服 warn 一次):${describeAllowlistPostures()};原文按凭据类对待:只回在场位、不进任何子进程,生效名单见起服披露行 allowed)`, { credentialForm: "
|
|
257
|
+
r("LSP_ENV_ALLOW", "orchestration", "secret", `host 腿语言服务器子进程 env 的点名放行名单(点到的键从服务 env 原样放回、部署方显式承担;没点到的照剥;与 host shell inheritEnv:[names] 同一只谓词;形错 / 点名任一只名单型旋钮(含自己)/ 点名本服务自有凭据 —— 名是,或值是本服务的某一枚凭据(另一个名下的副本)—— (剥后放回会把引擎刚扣下的凭据交回去;判官 = 引擎此刻的自有凭据声明)拒启且不回显值;本进程环境里没有的名按序号 warn、不放行、不回显;多租户姿态(忽略时起服 warn 一次):${describeAllowlistPostures()};原文按凭据类对待:只回在场位、不进任何子进程,生效名单见起服披露行 allowed)`, { credentialForm: "name-list", danger: SEC, derivedDefaultNote: "缺席 / 空串 ⇒ 空名单 = 全剥(7.100.0 行为)" }),
|
|
257
258
|
r("LSP_HOST_ENABLED", "orchestration", "boolean", "本机语言服务器开关(只在 host 车道且单主时挂;本机 language server,优雅降级)", { staticDefault: "true", configKey: "lspHostEnabled" }),
|
|
258
259
|
r("MANUAL_MODE_SHELL_GATE", "approval", "enum", "手动模式 shell 门收紧腿(off=no-op 非放松 —— 本键只有收紧半场;拼错拒启;classify 档已退役 = 拒启指路)", { danger: SEC, enumValues: ["always", "off"], echoWords: ["always"], resolve: (c) => c.manualModeShellGate ?? null, derivedDefaultNote: "off/未设 ⇒ 本键不贡献任何东西(归一成键缺席)⇒ 回显 null;真姿态只有 always 一个(core 7.34.0 起形状档在每一种模式下都装,classify 不再是运维选的档)" }),
|
|
259
260
|
r("MAX_PRINCIPAL_COST_USD", "limitsHttp", "number", "per-principal 窗内成本天花板(0=关)", { staticDefault: "0", danger: BILL, configKey: "maxPrincipalCostUsd", center: cLimits("maxPrincipalCostUsd") }),
|
|
@@ -462,6 +463,8 @@ export const CONFIG_CATALOG = [
|
|
|
462
463
|
r("SEMA_UV_INDEX", "orchestration", "url", "SANDBOX_PKG_SOURCE=custom 的显式 uv index 地址", { credentialPolicy: "refuse" }),
|
|
463
464
|
r("SEMA_UV_PY_MIRROR", "orchestration", "url", "SANDBOX_PKG_SOURCE=custom 的显式 uv python 分发镜像地址", { credentialPolicy: "refuse" }),
|
|
464
465
|
r(WEB_ADMIN_ENV.adminToken, "integrations", "secret", "写 web-admin 的管理凭证(仅 boot 上报执行公钥用;刻意不入 ServiceConfig —— 不进 configHash/日志面)", { credentialForm: "whole", danger: SEC, scope: "bootstrap-only" }),
|
|
466
|
+
r(WEB_ADMIN_ENV.assertionToken, "integrations", "secret", `web-admin 断言令牌(值形;编排器注入;与 ${WEB_ADMIN_ENV.assertionTokenFile} 二选一,都设=拒启)。唯一读者 = 中心凭证的声明读口(与 ${WEB_ADMIN_ENV.token} 同一只判官;只在接了中心 ${WEB_ADMIN_ENV.url} 时读):本版只报声明在 / 不在(/health center.assertionToken、起服日志 center_assertion_token),值不进配置、不向中心出示;它是本服务自有凭据,宿主子进程环境里扣掉`, { credentialForm: "whole", danger: SEC }),
|
|
467
|
+
r(WEB_ADMIN_ENV.assertionTokenFile, "integrations", "path", `web-admin 断言令牌文件(给不经编排器的手接引擎;与 ${WEB_ADMIN_ENV.assertionToken} 二选一,都设=拒启)。唯一读者同 ${WEB_ADMIN_ENV.assertionToken}:本版只报声明在 / 不在,不读文件内容`, { danger: SEC }),
|
|
465
468
|
r(WEB_ADMIN_ENV.dryRun, "integrations", "boolean", "web-admin 腿 dry-run(拉而不应用)", { staticDefault: "false", danger: SEC }),
|
|
466
469
|
r(WEB_ADMIN_ENV.liveUrl, "integrations", "url", `fleet 活性组(心跳 / 注销、服务租约 = settings-schema FLEET_LIVE_PATHS)的 web-admin 基址:给管理面在就绪门后、活性面另走一条不看就绪的入口的部署。缺席 = ${WEB_ADMIN_ENV.url}。传输地址,不参与中心身份互证。${CENTER_BASE_URL_RULE}`, { credentialPolicy: "refuse", danger: SEC }),
|
|
467
470
|
r(WEB_ADMIN_ENV.token, "integrations", "secret", `center 拉取凭据(值形;与 ${WEB_ADMIN_ENV.tokenFile} 二选一,都设=拒启)`, { credentialForm: "whole", danger: SEC }),
|
|
@@ -117,7 +117,8 @@ type AnonymousBoundaryView = Pick<CrossInvariantView, (typeof ANONYMOUS_BOUNDARY
|
|
|
117
117
|
* 写面无鉴权(`ALLOW_UNAUTHED_WRITES` ∧ 没配 service 凭据 = {@link bindMustNarrow})时,能连上这个口的都能不带主体提交 run;监听地址只在本机回环 ⇒ 能连上的只有本机,成立;
|
|
118
118
|
* 否则 ⇒ 网络上任何人都按那个人的规则跑 ⇒ 起服拒,拒句一行给两条出路:配凭据 / 只听本机回环。不加旋钮(两条出路都是既有键)。
|
|
119
119
|
* 写面无鉴权且零凭据时,监听地址缺省就收窄到 127.0.0.1(继承的 `HOST` 也压不过)⇒ 本条只在运维显式 `BIND_HOST` 把它暴露出去时成立。
|
|
120
|
-
*
|
|
120
|
+
* 写面要凭据的部署(没开逃生口)上能提交 run 的只有带着凭据门认的凭据的调用方(service 凭据持有者 / 鉴权桥验过的登录令牌 —— 后者恒带主体),不归本条;
|
|
121
|
+
* 配了 service 凭据的部署,调用方 = 凭据持有者(与 `operator-single-user-boundary` 同一道边界)。
|
|
121
122
|
* 「谁受伤」= 单用户 ∧ 写面无鉴权 ∧ 显式非回环 `BIND_HOST` 的部署(含容器里 `BIND_HOST=0.0.0.0`、宿主只发布到回环的那一形 —— 进程看不见宿主怎么发布端口);补偿 = 两条出路之一。
|
|
122
123
|
* **只在服务入口判**(起服第 1 段,紧跟 `operator-single-user-boundary`):律管开监听口的进程;`run-local` 不监听、同读 `loadConfig`,不在射程。
|
|
123
124
|
*/
|
|
@@ -6,11 +6,11 @@ import { modelRouteEndpointRefusal } from "./model-route-endpoint.js";
|
|
|
6
6
|
import { defaultModelRefusal, refusedNameMintedRefusal } from "./model-entry-refusal.js";
|
|
7
7
|
import { judgeEnvTableReplacement } from "./env-model-table-gate.js";
|
|
8
8
|
import { WEB_ADMIN_ENV, httpUrlFlaws } from "@sema-agent/settings-schema";
|
|
9
|
-
import { authBridgeIssuerOf } from "./identity-source.js";
|
|
9
|
+
import { authBridgeIssuerOf, hasServiceAuth } from "./identity-source.js";
|
|
10
10
|
import { buildDisplaySafeUrl } from "./trace/redact.js";
|
|
11
11
|
import { ALL_EXECUTION_LANES, executionLaneCaps } from "./execution-lane-caps.js";
|
|
12
12
|
import { DEPLOYMENT_SHAPE_PREDICATES } from "./deployment-shape.js";
|
|
13
|
-
import {
|
|
13
|
+
import { bindMustNarrow, listensLoopbackOnly, resolveBindHost } from "./bind-host.js";
|
|
14
14
|
export const LIVENESS_HEARTBEAT_MS = 30_000;
|
|
15
15
|
const directDoorConjuncts = (v) => Boolean(v.directApprovalDoor) && Boolean(v.durableApproval) && v.approvalHmacKeys.length > 0 && v.principalJwtPubkeys.length > 0 && Boolean(v.principalJwtIss) && Boolean(v.principalJwtAud);
|
|
16
16
|
function multiTenantSharedLaneRefusal(v) {
|
|
@@ -65,10 +65,10 @@ export function operatorDeclarationRefusal(v) {
|
|
|
65
65
|
}
|
|
66
66
|
const SINGLE_USER_BOUNDARY_KEYS = ["operatorSingleUser", "authToken", "authTokens", "allowUnauthedWrites", "bindHost", "bindHostSource"];
|
|
67
67
|
function sameSingleUserBoundary(a, b) {
|
|
68
|
-
return a.operatorSingleUser === b.operatorSingleUser &&
|
|
68
|
+
return a.operatorSingleUser === b.operatorSingleUser && hasServiceAuth(a) === hasServiceAuth(b) && resolveBindHost(a) === resolveBindHost(b);
|
|
69
69
|
}
|
|
70
70
|
export function operatorSingleUserBoundaryRefusal(v) {
|
|
71
|
-
if (v.operatorSingleUser !== true ||
|
|
71
|
+
if (v.operatorSingleUser !== true || hasServiceAuth(v))
|
|
72
72
|
return undefined;
|
|
73
73
|
const where = offHostListener(v);
|
|
74
74
|
if (where === undefined)
|